home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / demos / GL / flight / instr.c < prev    next >
C/C++ Source or Header  |  1994-08-01  |  105KB  |  4,558 lines

  1. /*
  2.  * Copyright 1990, 1991, 1992, 1993, 1994, Silicon Graphics, Inc.
  3.  * All Rights Reserved.
  4.  *
  5.  * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
  6.  * the contents of this file may not be disclosed to third parties, copied or
  7.  * duplicated in any form, in whole or in part, without the prior written
  8.  * permission of Silicon Graphics, Inc.
  9.  *
  10.  * RESTRICTED RIGHTS LEGEND:
  11.  * Use, duplication or disclosure by the Government is subject to restrictions
  12.  * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
  13.  * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
  14.  * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
  15.  * rights reserved under the Copyright Laws of the United States.
  16.  */
  17.  
  18. /*
  19.  *  flight/instr.c $Revision: 1.14 $
  20.  *
  21.  *  Instruments package for flight
  22.  */
  23.  
  24. #include "flight.h"
  25. #include <device.h>
  26. #include <math.h>
  27. #include <stdio.h>
  28. #include "light.h"
  29.  
  30.  
  31. #define INST_AR ((inst_x2+1 - inst_x1) / (float)(inst_y2+1 - inst_y1))
  32.  
  33. #define MARKINGS    2
  34.  
  35. #define P_MARKINGS    3
  36.  
  37. #define ICOLOR(col)    if (in_cmode) color(ci_table[col]); else cpack(col)
  38.  
  39. int maxspeed = 700;
  40. int plate_ci_mode = PUPDRAW;  /* what mode to draw plates in */
  41.  
  42. object_t *plate1;
  43. object_t *plate2;
  44. object_t *plate3;
  45. object_t *plate4;
  46. object_t *plate5;
  47. object_t *wlight;
  48.  
  49.  
  50. typedef struct inst_list {
  51.     int (*draw_func)();
  52.     int (*update_func)();
  53.     void *data;
  54.     struct inst_list *next;
  55. } inst_list_t;
  56.  
  57.  
  58.  
  59. static struct instrument_data
  60. {
  61.     unsigned char antialias;        /* If true, antialias the needles */
  62.     int charwide;            /* Width of a single character      */
  63.     int chartall;            /* Height of a char, no descender */
  64.     int threewide;            /* Width of three numbers      */
  65.     int twowide;            /* Width of two numbers          */
  66.     int fourwide;            /* Width of four numbers      */
  67.     int fivewide;            /* Width of five numbers      */
  68.     int sixwide;            /* Width of six numbers          */
  69.     int eightwide;            /* Width of eight numbers      */
  70.     int daytime;            /* True if daytime, else night      */
  71.     inst_list_t *inst_list;        /* List of instruments          */
  72.     int current;            /* 1 or 0: buffer being drawn      */
  73.     unsigned long jamblack;        /* Colors              */
  74.     unsigned long text;
  75.     unsigned long textborder;
  76.     unsigned long textbackground;
  77.     unsigned long yellow;
  78.     unsigned long darkneedle;
  79.     unsigned long lightneedle;
  80.     unsigned long redlamp;
  81.     unsigned long greenlamp;
  82.     unsigned long backlittext;
  83.     int force_update;
  84. } instrument_data;
  85.  
  86.  
  87. /*
  88.  *  Add an instrument to the instrument list.
  89.  */
  90. void append_inst_list(int (*draw_func)(), int (*update_func)(), void *data)
  91. {
  92.     inst_list_t *p;
  93.  
  94.     p = (inst_list_t *)malloc(sizeof(inst_list_t));
  95.     p->draw_func = draw_func;
  96.     p->update_func = update_func;
  97.     p->data = data;
  98.     p->next = instrument_data.inst_list;
  99.     instrument_data.inst_list = p;
  100. }
  101.  
  102.  
  103. /*
  104.  *  Erase the instrument list.
  105.  */
  106. void kill_inst_list()
  107. {
  108.     inst_list_t *p, *q;
  109.  
  110.     q = p = instrument_data.inst_list;
  111.     while (p)
  112.     {
  113.     p = p->next;
  114.     free(q);
  115.     q = p;
  116.     }
  117.     instrument_data.inst_list = NULL;
  118. }
  119.  
  120.  
  121. /*
  122.  *  Draw a four-sided polygon
  123.  */
  124. void drawneedlebox(float (*verts)[3])
  125. {
  126.     bgnpolygon();
  127.     v3f(verts[0]);
  128.     v3f(verts[1]);
  129.     v3f(verts[2]);
  130.     v3f(verts[3]);
  131.     endpolygon();
  132. }
  133.  
  134.  
  135. /*
  136.  *  Draw a needle.  First, draw the shadow, then the needle, then an
  137.  *  antialiased outline.
  138.  */
  139. void drawneedle(float ang, unsigned long col, float (*verts)[3])
  140. {
  141.     ICOLOR(instrument_data.jamblack);
  142.     setpattern(SHADOW_PATTERN);
  143.     pushmatrix();
  144.     translate(0.2, -0.2, 0.0);
  145.     rot(ang, 'z');
  146.     bgnpolygon();
  147.     v3f(verts[0]);
  148.     v3f(verts[1]);
  149.     v3f(verts[3]);
  150.     v3f(verts[4]);
  151.     endpolygon();
  152.     bgnpolygon();
  153.     v3f(verts[1]);
  154.     v3f(verts[2]);
  155.     v3f(verts[3]);
  156.     endpolygon();
  157.     setpattern(0);
  158.     popmatrix();
  159.     pushmatrix();
  160.     ICOLOR(col);
  161.     rot(ang, 'z');
  162.     bgnpolygon();
  163.     v3f(verts[0]);
  164.     v3f(verts[1]);
  165.     v3f(verts[3]);
  166.     v3f(verts[4]);
  167.     endpolygon();
  168.     bgnpolygon();
  169.     v3f(verts[1]);
  170.     v3f(verts[2]);
  171.     v3f(verts[3]);
  172.     endpolygon();
  173.     if (instrument_data.antialias)
  174.     {
  175.     if (!in_cmode)
  176.     {
  177.         blendfunction(BF_SA, BF_MSA);
  178.         linesmooth(SML_ON);
  179.     }
  180.     bgnline();
  181.     v3f(verts[0]);
  182.     v3f(verts[1]);
  183.     v3f(verts[2]);
  184.     v3f(verts[3]);
  185.     v3f(verts[4]);
  186.     endline();
  187.     if (!in_cmode)
  188.     {
  189.         linesmooth(SML_OFF);
  190.         blendfunction(BF_ONE, BF_ZERO);
  191.     }
  192.     }
  193.     popmatrix();
  194. }
  195.  
  196.  
  197. /*
  198.  * Initialize the instruments - set up some common data
  199.  */
  200. void init_instruments()
  201. {
  202.     static int firsttime = TRUE;
  203.  
  204.     if (in_cmode)
  205.     {
  206.     char gv_here[16];
  207.  
  208.     gversion(gv_here);  /* damn I hate how I'm doing this */
  209.     /* getgdesc(GD_CIFRACT) my ass.  All bitplanes, hah! */
  210.     if (strncmp(gv_here,"GL4DPI",6)==0)
  211.     {
  212.         plate_ci_mode = NORMALDRAW;
  213.     }
  214.     else
  215.         plate_ci_mode = PUPDRAW;
  216.     }
  217.  
  218.     instrument_data.charwide = strwidth("0")/2 - 1;
  219.     instrument_data.chartall = (getheight() - getdescender())/2 - 1;
  220.     instrument_data.twowide  = strwidth("00")/2 - 1;
  221.     instrument_data.threewide = strwidth("000")/2 - 1;
  222.     instrument_data.fourwide = strwidth("0000")/2 - 1;
  223.     instrument_data.fivewide = strwidth("00000")/2 - 1;
  224.     instrument_data.sixwide = strwidth("000000")/2 - 1;
  225.     instrument_data.eightwide = strwidth("00000000")/2 - 1;
  226.     instrument_data.current = 0;
  227.     instrument_data.antialias = getgdesc(GD_LINESMOOTH_RGB);
  228.  
  229.     if (firsttime)
  230.     {
  231.     char objfname[256];
  232.  
  233.     instrument_data.inst_list = NULL;
  234.  
  235.     strcpy(objfname, objdir);
  236.     strcat(objfname, "plate1.d");
  237.     plate1 = readobj(objfname);
  238.     strcpy(objfname, objdir);
  239.     strcat(objfname, "plate2.d");
  240.     plate2 = readobj(objfname);
  241.     strcpy(objfname, objdir);
  242.     strcat(objfname, "plate3.d");
  243.     plate3 = readobj(objfname);
  244.     strcpy(objfname, objdir);
  245.     strcat(objfname, "plate4.d");
  246.     plate4 = readobj(objfname);
  247.     strcpy(objfname, objdir);
  248.     strcat(objfname, "plate5.d");
  249.     plate5 = readobj(objfname);
  250.     strcpy(objfname, objdir);
  251.     strcat(objfname, "wlight.d");
  252.     wlight = readobj(objfname);
  253.     if (in_cmode && bits_cmode < 6)
  254.     {
  255.         remap_geom(&wlight->glist[1]);
  256.         remap_geom(&wlight->glist[2]);
  257.     }
  258.  
  259.     firsttime = FALSE;
  260.     }
  261.     else
  262.     {
  263.     kill_inst_list();
  264.     }
  265.  
  266.     /*
  267.      *  add_instruments
  268.      */
  269.     init_horizon(0.0, 4.0, 0.0, 0.8);
  270.     init_airspeed_meter(-15.0, 6.0, 0.0, 0.6, maxspeed);
  271.     init_mach_meter(-15.0, -7.0, 0.0, 0.6, 3.0, .5, 10);
  272.     init_altimeter(15.0, 6.0, 0.0, 0.6);
  273.     init_vertvel_meter(15.0, -7.0, 0.0, 0.6, 6000.0, 2000.0, 10);
  274.     init_fuelgauge(-32.0, 6.0, 0.0, 0.6, 50000.0, 10000.0, 5, 1000);
  275.     init_thrustthrottle(-32.0, -7.0, 0.0, 0.6, 25.0, 5);
  276.     init_radar(30.0, 4.0, 0.0, 0.8);
  277.     init_gmeter(-23.5, 2.5, 0.0, 0.6);
  278.     init_flapspoiler(25.5, -9.0, 0.0, 0.4, 60, 60, 6, 60, 60, 6);
  279.     init_gear(34.0, -9.0, 0.0, 0.4);
  280.     init_text_meter(0.0, -10.8, 0.0, 0.58);
  281.     init_stores_meter(0.0, -6.2, 0.0, 0.58);
  282.     init_wlight(-23.5, -8.5, 0.0, 0.5, &g_limit, "G-LIMIT");
  283.     init_wlight(-23.5, -11.5, 0.0, 0.5, &wing_stall, "WING STALL");
  284.  
  285.     set_instruments_time(1);
  286. }
  287.  
  288.  
  289. /*
  290.  * Set colors according to night/day
  291.  */
  292. void set_instruments_time(int daytime)
  293. {
  294.     long olddrawmode;
  295.  
  296.     if (daytime)
  297.     {
  298.     if (!in_cmode)
  299.     {
  300.         instrument_data.jamblack =        0xff010000;
  301.         instrument_data.text =        0xffdcdcdc;
  302.         instrument_data.textborder =    0xffa0a0a0;
  303.         instrument_data.textbackground =    0xff252525;
  304.         instrument_data.yellow =        0xff00d2d2;
  305.         instrument_data.lightneedle =    0xffe6e6e6;
  306.         instrument_data.darkneedle =    0xffc8c8c8;
  307.         instrument_data.redlamp =        0xff0000d0;
  308.         instrument_data.greenlamp =        0xff00d000;
  309.         instrument_data.backlittext =    0xff010101;
  310.     }
  311.     else {
  312.         instrument_data.jamblack =        C_BLACK;
  313.         instrument_data.text =        C_WHITE;
  314.         instrument_data.textborder =    C_GREY;
  315.         instrument_data.textbackground =    C_BLACK;
  316.         instrument_data.yellow =        C_ORANGE;
  317.         instrument_data.lightneedle =    C_GREY;
  318.         instrument_data.darkneedle =    C_GREY;
  319.         instrument_data.redlamp =        C_RED;
  320.         instrument_data.greenlamp =        C_GREEN;
  321.         instrument_data.backlittext =    C_BLACK;
  322.     }
  323.     }
  324.  
  325.     /* XXX Add night colors */
  326.  
  327.     instrument_data.daytime = daytime;
  328. }
  329.  
  330.  
  331. /*
  332.  *  Call all drawing functions in the draw list after setting up
  333.  *  viewing and lighting matrices.
  334.  */
  335. void draw_instruments()
  336. {
  337.     inst_list_t *p;
  338.     static float identity[4][4] = { 1.0, 0.0, 0.0, 0.0,
  339.                     0.0, 1.0, 0.0, 0.0,
  340.                     0.0, 0.0, 1.0, 0.0,
  341.                     0.0, 0.0, 0.0, 1.0 };
  342.  
  343.     viewport(inst_x1, inst_x2, inst_y1, inst_y2);
  344.  
  345.     perspective(100, INST_AR, 2.0, 1000.0);
  346.     pushmatrix();
  347.  
  348.     frontbuffer(TRUE);
  349.  
  350.     COLOR(C_GREY);
  351.     clear();
  352.     frontbuffer(FALSE);
  353.     if (!in_cmode)
  354.     zclear();
  355.  
  356.     translate(0.0, 0.0, -155.0);
  357.  
  358.     if (!in_cmode)
  359.     lmbind(LIGHT0, INST_LIGHT);
  360.  
  361.     p = instrument_data.inst_list;
  362.     while (p)
  363.     {
  364.     (*(p->draw_func))(p->data);
  365.     p = p->next;
  366.     }
  367.  
  368.     popmatrix();
  369.  
  370.     instrument_data.force_update = 2;
  371. }
  372.  
  373.  
  374. /*
  375.  * Call all update functions in update list
  376.  */
  377. void update_instruments(int forceupdate)
  378. {
  379.     inst_list_t *p;
  380.  
  381.     viewport(inst_x1, inst_x2, inst_y1, inst_y2);
  382.  
  383.     perspective(100, INST_AR, 2.0, 1000.0);
  384.  
  385.     pushmatrix();
  386.     translate(0.0, 0.0, -155.0);
  387.  
  388.     p = instrument_data.inst_list;
  389.     while (p)
  390.     {
  391.     (*(p->update_func))(p->data, instrument_data.force_update);
  392.     p = p->next;
  393.     }
  394.  
  395.     if (instrument_data.force_update > 0)
  396.     instrument_data.force_update--;
  397.  
  398.     instrument_data.current = !instrument_data.current;
  399.  
  400.     if (planes[0]->status <= MEXPLODE && !forceupdate)    /* if exploding or crashed      */
  401.     {
  402.     COLOR(C_WHITE);
  403.     setpattern(CRASH_PATTERN);    /* clear in crash pattern       */
  404.     clear();
  405.     setpattern(0);            /* reset pattern and color      */
  406.     }
  407.  
  408.     popmatrix();
  409. }
  410.  
  411.  
  412. clear_inst1()
  413. {
  414.     static float verts[4][3] = {{-9.0, -9.0}, {-9.0,  9.0},
  415.                 { 9.0,  9.0}, { 9.0, -9.0}};
  416.  
  417.     bgnpolygon();
  418.     v2f(verts[0]);
  419.     v2f(verts[1]);
  420.     v2f(verts[2]);
  421.     v2f(verts[3]);
  422.     endpolygon();
  423. }
  424.  
  425.  
  426. clear_inst2()
  427. {
  428.     static float verts[4][3] = {{-2.1, -15.1}, { 2.1, -15.1},
  429.                 { 2.1,  15.1}, {-2.1,  15.1}};
  430.  
  431.     bgnpolygon();
  432.     v2f(verts[0]);
  433.     v2f(verts[1]);
  434.     v2f(verts[2]);
  435.     v2f(verts[3]);
  436.     endpolygon();
  437. }
  438.  
  439.  
  440. clear_inst4()
  441. {
  442.     static float verts[4][3] = {{-13.1, -3.1}, {-13.1,  3.1},
  443.                 { 13.1,  3.1}, { 13.1, -3.1}};
  444.  
  445.     bgnpolygon();
  446.     v2f(verts[0]);
  447.     v2f(verts[1]);
  448.     v2f(verts[2]);
  449.     v2f(verts[3]);
  450.     endpolygon();
  451. }
  452.  
  453.  
  454. clear_inst5()
  455. {
  456.     static float verts[4][3] = {{-13.1, -2.6}, {-13.1,  2.6},
  457.                 { 13.1,  2.6}, { 13.1, -2.6}};
  458.  
  459.     bgnpolygon();
  460.     v2f(verts[0]);
  461.     v2f(verts[1]);
  462.     v2f(verts[2]);
  463.     v2f(verts[3]);
  464.     endpolygon();
  465. }
  466.  
  467.  
  468. /************************************************************************
  469. ***                Horizon functions              ***
  470. ************************************************************************/
  471.  
  472. typedef struct horizon_struct
  473. {
  474.     float px, py, pz;        /* Position of instrument */
  475.     float size;            /* Size of instrument */
  476.     short sm_l, sm_r, sm_b, sm_t;
  477.     object_t *plateobject;
  478. } horizon_t;
  479.  
  480.  
  481. /*
  482.  * Draw the artificial horizon
  483.  */
  484. draw_horizon(horizon_t *inst)
  485. {
  486.     static float bars[][2] = {{-6.6, -0.1}, {-3.0, -0.1},
  487.                   { 3.0, -0.1}, { 6.6, -0.1}};
  488.  
  489.     static float w[][2] = {{-3.34, -0.60},
  490.                {-1.97, -2.03},
  491.                { 0.00, -0.00},
  492.                { 2.00, -2.00},
  493.                { 3.40, -0.60}};
  494.     long ox, oy;
  495.  
  496.     pushmatrix();
  497.     translate(inst->px, inst->py, inst->pz);
  498.     scale(inst->size, inst->size, inst->size);
  499.  
  500.     /*
  501.      *  get instrument screen mask
  502.      */
  503.     cmov2i(-9.0, -9.0);
  504.     getcpos(&inst->sm_l, &inst->sm_b);
  505.     cmov2i(9.0, 9.0);
  506.     getcpos(&inst->sm_r, &inst->sm_t);
  507.     getorigin(&ox, &oy);
  508.     inst->sm_l -= ox;
  509.     inst->sm_r -= ox;
  510.     inst->sm_b -= oy;
  511.     inst->sm_t -= oy;
  512.  
  513.     if (!in_cmode)
  514.     {
  515.     /*
  516.      *  draw overlays
  517.      */
  518.     drawmode(PUPDRAW);
  519.  
  520.     color(P_ORANGE);
  521.     linewidth(3);
  522.     bgnline(); v2f(bars[0]); v2f(bars[1]); endline();
  523.     bgnline(); v2f(bars[2]); v2f(bars[3]); endline();
  524.     linewidth(2);
  525.     bgnline();
  526.     v2f(w[0]); v2f(w[1]); v2f(w[2]); v2f(w[3]); v2f(w[4]);
  527.     endline();
  528.     linewidth(1);
  529.     }
  530.  
  531.     /*
  532.      *  draw normal planes
  533.      */
  534.     drawmode(NORMALDRAW);
  535.  
  536.     frontbuffer(TRUE);
  537.  
  538.     COLOR(C_BLACK);
  539.     clear_inst1();
  540.  
  541.     draw_plate(inst->plateobject, 0x3);
  542.  
  543.     frontbuffer(FALSE);
  544.  
  545.     popmatrix();
  546. }
  547.  
  548. draw_horizon_ci(horizon_t *inst)
  549. {
  550.     static float bars[][2] = {{-6.6, -0.1}, {-3.0, -0.1},
  551.                   { 3.0, -0.1}, { 6.6, -0.1}};
  552.  
  553.     long ox, oy;
  554.  
  555.     pushmatrix();
  556.     translate(inst->px, inst->py, inst->pz);
  557.     scale(inst->size, inst->size, inst->size);
  558.  
  559.     /*
  560.      *  get instoment screen mask
  561.      */
  562.     cmov2i(-9.0, -9.0);
  563.     getcpos(&inst->sm_l, &inst->sm_b);
  564.     cmov2i(9.0, 9.0);
  565.     getcpos(&inst->sm_r, &inst->sm_t);
  566.     getorigin(&ox, &oy);
  567.     inst->sm_l -= ox;
  568.     inst->sm_r -= ox;
  569.     inst->sm_b -= oy;
  570.     inst->sm_t -= oy;
  571.  
  572.     /*
  573.      *  draw normal planes
  574.      */
  575.     drawmode(NORMALDRAW);
  576.  
  577.     frontbuffer(TRUE);
  578.  
  579.     COLOR(C_BLACK);
  580.     clear_inst1();
  581.  
  582.     drawmode(plate_ci_mode);
  583.     drawobj(inst->plateobject, 0x3);
  584.     drawmode(NORMALDRAW);
  585.  
  586.     frontbuffer(FALSE);
  587.  
  588.     popmatrix();
  589. }
  590.  
  591. /*
  592.  * Update the artificial horizon
  593.  */
  594. update_horizon(horizon_t *inst, int forceupdate)
  595. {
  596.     static float h_hi[][2] =  {{-9.0,   0.0},
  597.                    { 9.0,   0.0},
  598.                    { 9.0,  18.0},
  599.                    {-9.0,  18.0}};
  600.     static float h_low[][2] = {{ 9.0,   0.0},
  601.                    {-9.0,   0.0},
  602.                    {-9.0, -18.0},
  603.                    { 9.0, -18.0}};
  604.     static float bars[][2] = {{-3.0,  8.0}, {3.0,  8.0},
  605.                   {-1.0,  6.0}, {1.0,  6.0},
  606.                   {-1.5,  4.0}, {1.5,  4.0},
  607.                   {-1.0,  2.0}, {1.0,  2.0},
  608.                   {-3.0,  0.0}, {3.0,  0.0},
  609.                   {-1.0, -2.0}, {1.0, -2.0},
  610.                   {-1.5, -4.0}, {1.5, -4.0},
  611.                   {-1.0, -6.0}, {1.0, -6.0},
  612.                   {-3.0, -8.0}, {3.0, -8.0}};
  613.  
  614.     static float orange_bars[][2] = {{-6.6, -0.1}, {-3.0, -0.1},
  615.                      { 3.0, -0.1}, { 6.6, -0.1}};
  616.  
  617.     static float w[][2] = {{-3.34, -0.60},
  618.                {-1.97, -2.03},
  619.                { 0.00, -0.00},
  620.                { 2.00, -2.00},
  621.                { 3.40, -0.60}};
  622.  
  623.     pushmatrix();
  624.     translate(inst->px, inst->py, inst->pz);
  625.     scale(inst->size, inst->size, inst->size);
  626.     if (!in_cmode)
  627.     {
  628.     zbuffer(TRUE);
  629.     lsetdepth(zmaxscreen, zmaxscreen);
  630.     }
  631.     scrmask(inst->sm_l, inst->sm_r, inst->sm_b, inst->sm_t);
  632.  
  633.     pushmatrix();
  634.     rotate(-twist, 'z');
  635.     translate(0.0, -0.01 * elevation, 0.0);
  636.  
  637.     COLOR(C_HBLUE);
  638.     bgnpolygon();
  639.     v2f(h_hi[0]);
  640.     v2f(h_hi[1]);
  641.     v2f(h_hi[2]);
  642.     v2f(h_hi[3]);
  643.     endpolygon();
  644.  
  645.     COLOR(C_INST_BROWN);
  646.     bgnpolygon();
  647.     v2f(h_low[0]);
  648.     v2f(h_low[1]);
  649.     v2f(h_low[2]);
  650.     v2f(h_low[3]);
  651.     endpolygon();
  652.  
  653.     COLOR(C_WHITE);
  654.     bgnline(); v2f(bars[0]); v2f(bars[1]); endline();
  655.     bgnline(); v2f(bars[2]); v2f(bars[3]); endline();
  656.     bgnline(); v2f(bars[4]); v2f(bars[5]); endline();
  657.     bgnline(); v2f(bars[6]); v2f(bars[7]); endline();
  658.     bgnline(); v2f(bars[8]); v2f(bars[9]); endline();
  659.     bgnline(); v2f(bars[10]); v2f(bars[11]); endline();
  660.     bgnline(); v2f(bars[12]); v2f(bars[13]); endline();
  661.     bgnline(); v2f(bars[14]); v2f(bars[15]); endline();
  662.     bgnline(); v2f(bars[16]); v2f(bars[17]); endline();
  663.  
  664.     scrmask(0, xmaxwindow, 0, ymaxwindow);
  665.     popmatrix();
  666.  
  667.     if (!in_cmode)
  668.     {
  669.     lsetdepth(zminscreen, zmaxscreen);
  670.     zbuffer(FALSE);
  671.     }
  672.     else
  673.     {
  674.     color(ci_table[C_ORANGE]);
  675.     linewidth(3);
  676.     bgnline(); v2f(orange_bars[0]); v2f(orange_bars[1]); endline();
  677.     bgnline(); v2f(orange_bars[2]); v2f(orange_bars[3]); endline();
  678.     linewidth(2);
  679.     bgnline();
  680.     v2f(w[0]); v2f(w[1]); v2f(w[2]); v2f(w[3]); v2f(w[4]);
  681.     endline();
  682.     linewidth(1);
  683.     }
  684.  
  685.     popmatrix();
  686. }
  687.  
  688.  
  689. /*
  690.  * Initialize the horizon's private data and add its functions to
  691.  * the drawing lists
  692.  */
  693. void init_horizon(float px, float py, float pz, float size)
  694. {
  695.     horizon_t *inst;
  696.  
  697.     inst = (horizon_t *)malloc(sizeof(*inst));
  698.     bzero(inst, sizeof(*inst));
  699.     inst->plateobject = plate1;
  700.     inst->px = px;
  701.     inst->py = py;
  702.     inst->pz = pz;
  703.     inst->size = size;
  704.  
  705.     append_inst_list(draw_horizon, update_horizon, inst);
  706. }
  707.  
  708.  
  709. /************************************************************************
  710. ***            warning light functions                  ***
  711. ************************************************************************/
  712.  
  713. typedef struct {
  714.     float px, py, pz;        /* Position of instrument */
  715.     float size;            /* Size of instrument */
  716.     object_t *plateobject;
  717.     char label[16];
  718.     short *warning;
  719.     short last_state[2];
  720. } wlight_t;
  721.  
  722.  
  723. /*
  724.  * Draw the artificial wlight
  725.  */
  726. draw_wlight(wlight_t *inst)
  727. {
  728.     pushmatrix();
  729.     translate(inst->px, inst->py, inst->pz);
  730.     scale(inst->size, inst->size, inst->size);
  731.  
  732.     frontbuffer(TRUE);
  733.  
  734.     if (!in_cmode)
  735.     {
  736.     zbuffer(TRUE);
  737.     lighting(TRUE);
  738.     drawobj(inst->plateobject, 0x3);
  739.     lighting(FALSE);
  740.     zbuffer(FALSE);
  741.  
  742.     cpack(0xff010101);
  743.     }
  744.     else
  745.     {
  746.     drawmode(plate_ci_mode);
  747.     drawobj(inst->plateobject, 0x9);
  748.     drawmode(NORMALDRAW);
  749.     drawobj(inst->plateobject, 0x2);
  750.  
  751.     color(ci_table[C_BLACK]);
  752.     }
  753.  
  754.     cmov2(-0.12 * (strwidth(inst->label) / 2.0), -3.3);
  755.     charstr(inst->label);
  756.  
  757.     frontbuffer(FALSE);
  758.  
  759.     popmatrix();
  760. }
  761.  
  762.  
  763.  
  764. /*
  765.  * Update the artificial wlight
  766.  */
  767. update_wlight(wlight_t *inst, int forceupdate)
  768. {
  769.     pushmatrix();
  770.     translate(inst->px, inst->py, inst->pz);
  771.     scale(inst->size, inst->size, inst->size);
  772.  
  773.     frontbuffer(TRUE);
  774.  
  775.     if (!in_cmode)
  776.     {
  777.     zbuffer(TRUE);
  778.     lighting(TRUE);
  779.     }
  780.     if (inst->last_state[instrument_data.current] != *(inst->warning))
  781.     {
  782.     if (inst->last_state[instrument_data.current] = *(inst->warning))
  783.         drawobj(inst->plateobject, 0x4);
  784.     else
  785.         drawobj(inst->plateobject, 0x2);
  786.     }
  787.     if (!in_cmode)
  788.     {
  789.     lighting(FALSE);
  790.     zbuffer(FALSE);
  791.     }
  792.  
  793.     frontbuffer(FALSE);
  794.  
  795.     popmatrix();
  796. }
  797.  
  798.  
  799.  
  800. /*
  801.  * Initialize the wlight's private data and add its functions to
  802.  * the drawing lists
  803.  */
  804. void init_wlight(float px, float py, float pz, float size, short *warning, char *label)
  805. {
  806.     wlight_t *inst;
  807.  
  808.     inst = (wlight_t *)malloc(sizeof(*inst));
  809.     bzero(inst, sizeof(*inst));
  810.     inst->plateobject = wlight;
  811.     inst->px = px;
  812.     inst->py = py;
  813.     inst->pz = pz;
  814.     inst->size = size;
  815.     inst->warning = warning;
  816.     strncpy(inst->label, label, 16);
  817.  
  818.     append_inst_list(draw_wlight, update_wlight, inst);
  819. }
  820.  
  821.  
  822. /************************************************************************
  823. ***            Text Meter functions                  ***
  824. ************************************************************************/
  825.  
  826. #define TEXT_METER_LINES 2
  827.  
  828. typedef struct {
  829.     float px, py, pz;        /* Position of instrument */
  830.     float size;            /* Size of instrument */
  831.     object_t *plateobject;
  832.     char text[TEXT_METER_LINES][80];
  833.     int textdrawn[2];
  834.     int timeout[TEXT_METER_LINES];
  835. } text_meter_t;
  836.  
  837.  
  838. /*
  839.  * Draw the text_meter
  840.  */
  841. draw_text_meter(text_meter_t *inst)
  842. {
  843.     pushmatrix();
  844.     translate(inst->px, inst->py, inst->pz);
  845.     scale(inst->size, inst->size, inst->size);
  846.  
  847.     drawmode(NORMALDRAW);
  848.  
  849.     frontbuffer(TRUE);
  850.  
  851.     COLOR(C_BLACK);
  852.     clear_inst4();
  853.  
  854.     draw_plate(inst->plateobject, 0x3);
  855.  
  856.     frontbuffer(FALSE);
  857.  
  858.     popmatrix();
  859. }
  860.  
  861.  
  862. /*
  863.  * Update the text_meter's state
  864.  */
  865. update_text_meter(text_meter_t *inst, int forceupdate)
  866. {
  867.     int i;
  868.  
  869.     pushmatrix();
  870.     translate(inst->px, inst->py, inst->pz);
  871.     scale(inst->size, inst->size, inst->size);
  872.  
  873.     for (i=0; i < TEXT_METER_LINES; i++)
  874.     {
  875.     if (inst->timeout[i] > 0)
  876.         inst->timeout[i]--;
  877.     else if (inst->timeout[i] == 0)
  878.     {
  879.         inst->timeout[i] = -1;
  880.         inst->text[i][0] = '\0';
  881.         inst->textdrawn[0] = 0;
  882.         inst->textdrawn[1] = 0;
  883.     }
  884.     }
  885.  
  886.     if (!inst->textdrawn[instrument_data.current])
  887.     {
  888.     zbuffer(!in_cmode);
  889.     COLOR(C_BLACK);
  890.     clear_inst4();
  891.     zbuffer(FALSE);
  892.  
  893.     COLOR(C_WHITE);
  894.     for (i=0; i < TEXT_METER_LINES; i++)
  895.     {
  896.         cmov2(-12.0, 1.0 - i*2);
  897.         charstr(inst->text[i]);
  898.     }
  899.     inst->textdrawn[instrument_data.current] = 1;
  900.     }
  901.     popmatrix();
  902. }
  903.  
  904. static text_meter_t *tm;
  905.  
  906.  
  907. /*
  908.  * Initialize the text_meter's private data and add its functions to
  909.  * the drawing lists
  910.  */
  911. void init_text_meter(float px, float py, float pz, float size)
  912. {
  913.     text_meter_t *inst;
  914.     int i;
  915.  
  916.     inst = (text_meter_t *)malloc(sizeof(*inst));
  917.     bzero(inst, sizeof(*inst));
  918.     inst->plateobject = plate4;
  919.     inst->px = px;
  920.     inst->py = py;
  921.     inst->pz = pz;
  922.     inst->size = size;
  923.     for (i=0; i < TEXT_METER_LINES; i++)
  924.     {
  925.     inst->text[i][0] = 0;
  926.     inst->timeout[i] = -1;
  927.     }
  928.     inst->textdrawn[0] = 1;
  929.     inst->textdrawn[1] = 1;
  930.     tm = inst;
  931.  
  932.     append_inst_list(draw_text_meter, update_text_meter, inst);
  933. }
  934.  
  935.  
  936. /*
  937.  * set text_meter text
  938.  */
  939. void set_text_meter(int lnum, char *text, int timeout)
  940. {
  941.     strncpy(tm->text[lnum], text, 80);
  942.     tm->textdrawn[0] = 0;
  943.     tm->textdrawn[1] = 0;
  944.     tm->timeout[lnum] = timeout;
  945. }
  946.  
  947.  
  948. /************************************************************************
  949. ***            Storess Meter functions                  ***
  950. ************************************************************************/
  951.  
  952. typedef struct {
  953.     float px, py, pz;        /* Position of instrument */
  954.     float size;            /* Size of instrument */
  955.     int last_sw[2];
  956.     int last_rk[2];
  957.     object_t *plateobject;
  958. } stores_meter_t;
  959.  
  960.  
  961. /*
  962.  * Draw the stores_meter
  963.  */
  964. draw_stores_meter(stores_meter_t *inst)
  965. {
  966.     pushmatrix();
  967.     translate(inst->px, inst->py, inst->pz);
  968.     scale(inst->size, inst->size, inst->size);
  969.  
  970.     if (in_cmode)
  971.     {
  972.     drawmode(NORMALDRAW);
  973.     color(ci_table[C_BLACK]);
  974.     clear_inst5();
  975.  
  976.     drawmode(plate_ci_mode);
  977.     color(0);
  978.     clear_inst5();
  979.     color(P_MARKINGS);
  980.     }
  981.     else
  982.     {
  983.     drawmode(UNDERDRAW);
  984.  
  985.     color(U_INST);
  986.     clear_inst5();
  987.  
  988.     color(MARKINGS);
  989.     }
  990.  
  991.     cmov2(-12.0, -1.6);
  992.     charstr("Sidewinders");
  993.     cmov2(4.0, -1.6);
  994.     charstr("Rockets");
  995.  
  996.     drawmode(NORMALDRAW);
  997.  
  998.     frontbuffer(TRUE);
  999.  
  1000.     COLOR(C_BLACK);
  1001.     clear_inst5();
  1002.  
  1003.     draw_plate(inst->plateobject, 0x3);
  1004.  
  1005.     frontbuffer(FALSE);
  1006.  
  1007.     popmatrix();
  1008. }
  1009.  
  1010.  
  1011. /*
  1012.  * Update the stores_meter's state
  1013.  */
  1014. update_stores_meter(stores_meter_t *inst, int forceupdate)
  1015. {
  1016.     int i;
  1017.  
  1018.     pushmatrix();
  1019.     translate(inst->px, inst->py, inst->pz);
  1020.     scale(inst->size, inst->size, inst->size);
  1021.  
  1022.     if (inst->last_sw[instrument_data.current] != sidewinders ||
  1023.     inst->last_rk[instrument_data.current] != rockets ||
  1024.     forceupdate)
  1025.     {
  1026.     if (in_cmode)
  1027.         zbuffer(TRUE);
  1028.  
  1029.     COLOR(C_BLACK);
  1030.     clear_inst5();
  1031.  
  1032.     if (in_cmode)
  1033.         zbuffer(FALSE);
  1034.  
  1035.     if (MAX_SW >= 3)
  1036.     {
  1037.         if (sidewinders >= 3)
  1038.         COLOR(C_RED);
  1039.         else
  1040.         COLOR(C_DRED);
  1041.         circf(-10.0, 1.0, 0.62);
  1042.         COLOR(C_WHITE);
  1043.         circ(-10.0, 1.0, 0.62);
  1044.     }
  1045.  
  1046.     if (MAX_SW >= 1)
  1047.     {
  1048.         if (sidewinders >= 1)
  1049.         COLOR(C_RED);
  1050.         else
  1051.         COLOR(C_DRED);
  1052.         circf(-8.0, 1.0, 0.62);
  1053.         COLOR(C_WHITE);
  1054.         circ(-8.0, 1.0, 0.62);
  1055.     }
  1056.  
  1057.     if (MAX_SW >= 2)
  1058.     {
  1059.         if (sidewinders >= 2)
  1060.         COLOR(C_RED);
  1061.         else
  1062.         COLOR(C_DRED);
  1063.         circf(-6.0, 1.0, 0.62);
  1064.         COLOR(C_WHITE);
  1065.         circ(-6.0, 1.0, 0.62);
  1066.     }
  1067.  
  1068.     if (MAX_SW >= 4)
  1069.     {
  1070.         if (sidewinders >= 4)
  1071.         COLOR(C_RED);
  1072.         else
  1073.         COLOR(C_DRED);
  1074.         circf(-4.0, 1.0, 0.62);
  1075.         COLOR(C_WHITE);
  1076.         circ(-4.0, 1.0, 0.62);
  1077.     }
  1078.  
  1079.     if (MAX_RK >= 3)
  1080.     {
  1081.         if (rockets >= 3)
  1082.         COLOR(C_RED);
  1083.         else
  1084.         COLOR(C_DRED);
  1085.         circf(10.0, 1.0, 0.62);
  1086.         COLOR(C_WHITE);
  1087.         circ(10.0, 1.0, 0.62);
  1088.     }
  1089.  
  1090.     if (MAX_RK >= 1)
  1091.     {
  1092.         if (rockets >= 1)
  1093.         COLOR(C_RED);
  1094.         else
  1095.         COLOR(C_DRED);
  1096.         circf(8.0, 1.0, 0.62);
  1097.         COLOR(C_WHITE);
  1098.         circ(8.0, 1.0, 0.62);
  1099.     }
  1100.  
  1101.     if (MAX_RK >= 2)
  1102.     {
  1103.         if (rockets >= 2)
  1104.         COLOR(C_RED);
  1105.         else
  1106.         COLOR(C_DRED);
  1107.         circf(6.0, 1.0, 0.62);
  1108.         COLOR(C_WHITE);
  1109.         circ(6.0, 1.0, 0.62);
  1110.     }
  1111.  
  1112.     if (MAX_RK >= 4)
  1113.     {
  1114.         if (rockets >= 4)
  1115.         COLOR(C_RED);
  1116.         else
  1117.         COLOR(C_DRED);
  1118.         circf(4.0, 1.0, 0.62);
  1119.         COLOR(C_WHITE);
  1120.         circ(4.0, 1.0, 0.62);
  1121.     }
  1122.  
  1123.     inst->last_sw[instrument_data.current] = sidewinders;
  1124.     inst->last_rk[instrument_data.current] = rockets;
  1125.     }
  1126.  
  1127.     popmatrix();
  1128. }
  1129.  
  1130. static stores_meter_t *sm;
  1131.  
  1132.  
  1133. /*
  1134.  * Initialize the stores_meter's private data and add its functions to
  1135.  * the drawing lists
  1136.  */
  1137. void init_stores_meter(float px, float py, float pz, float size)
  1138. {
  1139.     stores_meter_t *inst;
  1140.     int i;
  1141.  
  1142.     inst = (stores_meter_t *)malloc(sizeof(*inst));
  1143.     bzero(inst, sizeof(*inst));
  1144.     inst->plateobject = plate5;
  1145.     inst->px = px;
  1146.     inst->py = py;
  1147.     inst->pz = pz;
  1148.     inst->size = size;
  1149.     sm = inst;
  1150.  
  1151.     append_inst_list(draw_stores_meter, update_stores_meter, inst);
  1152. }
  1153.  
  1154.  
  1155. /*
  1156.  * set stores_meter
  1157.  */
  1158. void set_stores_meter()
  1159. {
  1160. }
  1161.  
  1162.  
  1163. /************************************************************************
  1164. ***                Altimeter functions              ***
  1165. ************************************************************************/
  1166.  
  1167.  
  1168. typedef struct altimeter_struct
  1169. {
  1170.     float px, py, pz;        /* Position of instrument */
  1171.     float size;            /* Size of instrument */
  1172.     float last_alt[2];        /* Previous altitudes of both buffers */
  1173.     float last_rot1000[2];
  1174.     float last_rot100[2];
  1175.     object_t *plateobject;
  1176.     int framec;
  1177.     int warningup;
  1178.     int warningdown;
  1179.     int numframes;
  1180.     int displayagain;
  1181.     float scale;
  1182.     int old10;
  1183.     float scrollalt;
  1184.     float scale10;
  1185.     char high10str[4];
  1186.     char low10str[4];
  1187. } altimeter_t;
  1188.  
  1189.  
  1190.  
  1191. /*
  1192.  * Draw the altimeter
  1193.  */
  1194. draw_altimeter(altimeter_t *inst)
  1195. {
  1196.     static float verts[4][3] = {{-9.0, -9.0, 0.0}, {-9.0, 9.0, 0.0},
  1197.                 {9.0, 9.0, 0.0}, {9.0, -9.0, 0.0}};
  1198.     static float ticks[3][3] = { 0.0,7.7,0.0, 0.0,9.0,0.0, 0.0,8.3,0.0 };
  1199.     short sl, sr, sb, st;
  1200.     char s[4];
  1201.     int i, x;
  1202.  
  1203.     pushmatrix();
  1204.     translate(inst->px, inst->py, inst->pz);
  1205.     scale(inst->size, inst->size, inst->size);
  1206.     drawmode(UNDERDRAW);
  1207.  
  1208.     color(U_INST);
  1209.     clear_inst1();
  1210.  
  1211.     color(MARKINGS);
  1212.     for (x=0; x<3600; x+=360)
  1213.     {
  1214.     bgnline();
  1215.     v3f(ticks[0]);
  1216.     v3f(ticks[1]);
  1217.     endline();
  1218.     rotate(-360, 'z');
  1219.     }
  1220.     for (x=0; x<3600; x+=72)
  1221.     {
  1222.     if (x%360)
  1223.     {
  1224.         bgnline();
  1225.         v3f(ticks[2]);
  1226.         v3f(ticks[1]);
  1227.         endline();
  1228.     }
  1229.     rotate(-72, 'z');
  1230.     }
  1231.     pushviewport();
  1232.     getviewport(&sl, &sr, &sb, &st);
  1233.     viewport(sl-instrument_data.threewide, sr-instrument_data.threewide,
  1234.          sb-instrument_data.chartall, st-instrument_data.chartall);
  1235.     cmov(0.0, -5.2, 0.0);
  1236.     charstr("ALT");
  1237.     popviewport();
  1238.     pushviewport();
  1239.     viewport(sl-instrument_data.charwide, sr-instrument_data.charwide,
  1240.          sb-instrument_data.chartall, st-instrument_data.chartall);
  1241.     i = 0;
  1242.     for (x=0; x<3600; x+=360)
  1243.     {
  1244.     sprintf(s, "%d", i++);
  1245.     cmov(0.0, 7.0, 0.0);
  1246.     charstr(s);
  1247.     rotate(-360, 'z');
  1248.     }
  1249.     popviewport();
  1250.     drawmode(NORMALDRAW);
  1251.     frontbuffer(TRUE);
  1252.  
  1253.     COLOR(C_BLACK);
  1254.     clear_inst1();
  1255.  
  1256.     draw_plate(inst->plateobject, 0x3);
  1257.  
  1258.     frontbuffer(FALSE);
  1259.     popmatrix();
  1260. }
  1261.  
  1262. draw_altimeter_ci(altimeter_t *inst)
  1263. {
  1264.     static float verts[4][3] = {{-9.0, -9.0, 0.0}, {-9.0, 9.0, 0.0},
  1265.                 {9.0, 9.0, 0.0}, {9.0, -9.0, 0.0}};
  1266.     static float ticks[3][3] = { 0.0,7.7,0.0, 0.0,9.0,0.0, 0.0,8.3,0.0 };
  1267.     short sl, sr, sb, st;
  1268.     char s[4];
  1269.     int i, x;
  1270.  
  1271.     pushmatrix();
  1272.     translate(inst->px, inst->py, inst->pz);
  1273.     scale(inst->size, inst->size, inst->size);
  1274.  
  1275.     color(ci_table[C_BLACK]);
  1276.     clear_inst1();
  1277.  
  1278.     drawmode(PUPDRAW);
  1279.     color(U_BLACK);
  1280.     clear_inst1();
  1281.  
  1282.     color(P_MARKINGS);
  1283.     for (x=0; x<3600; x+=360)
  1284.     {
  1285.     bgnline();
  1286.     v3f(ticks[0]);
  1287.     v3f(ticks[1]);
  1288.     endline();
  1289.     rotate(-360, 'z');
  1290.     }
  1291.     for (x=0; x<3600; x+=72)
  1292.     {
  1293.     if (x%360)
  1294.     {
  1295.         bgnline();
  1296.         v3f(ticks[2]);
  1297.         v3f(ticks[1]);
  1298.         endline();
  1299.     }
  1300.     rotate(-72, 'z');
  1301.     }
  1302.     pushviewport();
  1303.     getviewport(&sl, &sr, &sb, &st);
  1304.     viewport(sl-instrument_data.threewide, sr-instrument_data.threewide,
  1305.          sb-instrument_data.chartall, st-instrument_data.chartall);
  1306.     cmov(0.0, -5.2, 0.0);
  1307.     charstr("ALT");
  1308.     popviewport();
  1309.     pushviewport();
  1310.     viewport(sl-instrument_data.charwide, sr-instrument_data.charwide,
  1311.          sb-instrument_data.chartall, st-instrument_data.chartall);
  1312.     i = 0;
  1313.     for (x=0; x<3600; x+=360)
  1314.     {
  1315.     sprintf(s, "%d", i++);
  1316.     color(P_MARKINGS);
  1317.     cmov(0.0, 7.0, 0.0);
  1318.     charstr(s);
  1319.     rotate(-360, 'z');
  1320.     }
  1321.     popviewport();
  1322.  
  1323.     drawmode(plate_ci_mode);
  1324.     drawobj(inst->plateobject, 0x3);
  1325.  
  1326.     drawmode(NORMALDRAW);
  1327.     frontbuffer(TRUE);
  1328.  
  1329.     color(ci_table[C_BLACK]);
  1330.     clear_inst1();
  1331.  
  1332.     frontbuffer(FALSE);
  1333.     color(ci_table[C_BLACK]);
  1334.     clear_inst1();
  1335.  
  1336.     popmatrix();
  1337. }
  1338.  
  1339.  
  1340.  
  1341. /*
  1342.  * Update the altimeter's needles
  1343.  */
  1344. update_altimeter(altimeter_t *inst, int forceupdate)
  1345. {
  1346.     static float lowstripes[16][3] = { -1.5,-4.5,0.0, -2.25,-4.5,0.0,
  1347.         -1.0,-3.25,0.0, -1.0,-4.0,0.0, -3.0,-4.5,0.0, -3.75,-4.5,0.0,
  1348.         -1.25,-2.0,0.0, -1.0,-2.5,0.0, -4.5,-4.5,0.0, -4.5,-3.75,0.0,
  1349.         -2.75,-2.0,0.0, -2.0,-2.0,0.0, -4.5,-3.0,0.0, -4.5,-2.0,0.0,
  1350.         -3.5,-2.0,0.0, -1.0,-2.0,0.0 };
  1351.     static float box10[4][3]  = { -4.5,-4.5,0.0, -1.0,-4.5,0.0, -1.0,-2.0,0.0,
  1352.         -4.5,-2.0,0.0 };
  1353.     static float boxt10[4][3] = { -4.5,-2.0,0.0, -1.0,-2.0,0.0, -1.0,.5,0.0,
  1354.         -4.5,.5,0.0 };
  1355.     static float boxb10[4][3] = { -4.5,-7.0,0.0, -1.0,-7.0,0.0, -1.0,-4.5,0.0,
  1356.         -4.5,-4.5,0.0 };
  1357.     static float needle1000[5][3] = {-.3,0.0,0.0, -.3,4.0,0.0, 0.0,5.0,0.0,
  1358.         .3,4.0,0.0, .3,0.0,0.0};
  1359.     static float needle100[5][3]  = {-.2,0.0,0.0, -.2,5.0,0.0, 0.0,7.0,0.0,
  1360.         .2,5.0,0.0, .2,0.0,0.0 };
  1361.     static float needle1000box[5][3] = {-.7,-.8,0.0, -.7,5.3,0.0, .7,5.3,0.0,
  1362.         .7,-.8,0.0 };
  1363.     static float needle100box[5][3]  = {-.7,-.3,0.0, -.7,7.3,0.0, .7,7.3,0.0,
  1364.         .7,-.3,0.0};
  1365.     static float cx= -3.5, cy= -3.7, cz=0.0; /* Pos of text for 10K ft. meter */
  1366.     int current;
  1367.     int new10= 0;
  1368.     int old10= 0;
  1369.     char buf[5];
  1370.     float alt1000;
  1371.     float altitude;
  1372.     Plane pp = planes[0];
  1373.  
  1374.     altitude = pp->y - plane_height;
  1375.  
  1376.     current = instrument_data.current;
  1377.  
  1378.     pushmatrix();
  1379.     translate(inst->px, inst->py, inst->pz);
  1380.     scale(inst->size, inst->size, inst->size);
  1381.     if ((altitude != inst->last_alt[current]) || forceupdate ||
  1382.         (inst->framec + inst->displayagain))
  1383.     {
  1384.     if (inst->displayagain) inst->displayagain--;
  1385.     cpack(0x00000000);    /* Clear old display */
  1386.     pushmatrix();
  1387.     rot(inst->last_rot1000[current], 'z');
  1388.     drawneedlebox(needle1000box);
  1389.     popmatrix();
  1390.     pushmatrix();
  1391.     rot(inst->last_rot100[current], 'z');
  1392.     drawneedlebox(needle100box);
  1393.     popmatrix();
  1394. #ifndef NO_MS
  1395.     if (ms_samples)
  1396.     {
  1397.         pushmatrix();
  1398.         rot(inst->last_rot1000[!current], 'z');
  1399.         drawneedlebox(needle1000box);
  1400.         popmatrix();
  1401.         pushmatrix();
  1402.         rot(inst->last_rot100[!current], 'z');
  1403.         drawneedlebox(needle100box);
  1404.         popmatrix();
  1405.     }
  1406. #endif
  1407.  
  1408.     ICOLOR(instrument_data.textbackground);
  1409.     drawneedlebox(box10);
  1410.  
  1411.     new10 = (int)altitude/10000;
  1412.     old10 = (int)inst->last_alt[current]/10000;
  1413.     if ((new10 == 0)&&(old10 == 1))
  1414.     {
  1415.         inst->warningdown = -1;
  1416.         inst->warningup = 0;
  1417.         if (!inst->framec) inst->framec = inst->numframes;
  1418.     }
  1419.     else if ((new10 == 1)&&(old10 == 0))
  1420.     {
  1421.         inst->warningdown = 0;
  1422.         inst->warningup = 1;
  1423.         if (!inst->framec) inst->framec = 1;
  1424.     }
  1425.  
  1426.     if ((altitude < 10000) || (inst->warningup+inst->warningdown))
  1427.     {
  1428.         if (inst->framec)
  1429.         {
  1430.         pushmatrix();
  1431.  
  1432.         ICOLOR(instrument_data.text);
  1433.         cmov(cx, cy, cz);
  1434.         charstr("10");
  1435.         translate(0.0, inst->scale * inst->framec, 0.0);
  1436.         ICOLOR(instrument_data.textbackground);
  1437.         drawneedlebox(box10);
  1438.         }
  1439.         ICOLOR(instrument_data.yellow);
  1440.         bgnpolygon();
  1441.         v3f(lowstripes[0]);
  1442.         v3f(lowstripes[1]);
  1443.         v3f(lowstripes[2]);
  1444.         v3f(lowstripes[3]);
  1445.         endpolygon();
  1446.         bgnpolygon();
  1447.         v3f(lowstripes[4]);
  1448.         v3f(lowstripes[5]);
  1449.         v3f(lowstripes[6]);
  1450.         v3f(lowstripes[15]);
  1451.         v3f(lowstripes[7]);
  1452.         endpolygon();
  1453.         bgnpolygon();
  1454.         v3f(lowstripes[8]);
  1455.         v3f(lowstripes[9]);
  1456.         v3f(lowstripes[10]);
  1457.         v3f(lowstripes[11]);
  1458.         endpolygon();
  1459.         bgnpolygon();
  1460.         v3f(lowstripes[12]);
  1461.         v3f(lowstripes[13]);
  1462.         v3f(lowstripes[14]);
  1463.         endpolygon();
  1464.         if (inst->framec)
  1465.         {
  1466.         popmatrix();
  1467.         cpack(0x00000000);
  1468.         bgnpolygon();
  1469.         v3f(boxt10[0]);
  1470.         v3f(boxt10[1]);
  1471.         v3f(boxt10[2]);
  1472.         v3f(boxt10[3]);
  1473.         endpolygon();
  1474.         inst->framec = (inst->framec + inst->warningup
  1475.                 + inst->warningdown) % inst->numframes;
  1476.         if (!inst->framec)
  1477.         {
  1478.             inst->warningup = inst->warningdown = 0;
  1479.             inst->displayagain = 2;
  1480.         }
  1481.         }
  1482.     }
  1483.     else if ((alt1000=(10000.0-fmod(altitude, 10000.0))) <
  1484.          inst->scrollalt)
  1485.     {
  1486.         pushmatrix();
  1487.         ICOLOR(instrument_data.text);
  1488.         translate(0.0,(inst->scrollalt-alt1000)*inst->scale10,0.0);
  1489.         if (inst->old10 != new10)
  1490.         {
  1491.         sprintf(inst->low10str,"%d",new10*10);
  1492.         sprintf(inst->high10str,"%d",(new10+1)*10);
  1493.         }
  1494.         cmov(cx,cy,cz);
  1495.         charstr(inst->low10str);
  1496.         translate(0.0, -2.5, 0.0);
  1497.         cmov(cx,cy,cz);
  1498.         charstr(inst->high10str);
  1499.         popmatrix();
  1500.         cpack(0x00000000);
  1501.         drawneedlebox(boxt10);
  1502.         drawneedlebox(boxb10);
  1503.     }
  1504.     else
  1505.     {
  1506.         ICOLOR(instrument_data.text);
  1507.         sprintf(buf,"%d",new10*10);
  1508.         cmov(cx,cy,cz);
  1509.         charstr(buf);
  1510.     }
  1511.     ICOLOR(instrument_data.textborder);
  1512.     bgnclosedline();
  1513.     v3f(box10[0]);
  1514.     v3f(box10[1]);
  1515.     v3f(box10[2]);
  1516.     v3f(box10[3]);
  1517.     endclosedline();
  1518.     inst->last_rot1000[current]=(int)(fmod(altitude,10000.0)*-.036);
  1519.     inst->last_rot100[current] =(int)(fmod(altitude, 1000.0)*-.36);
  1520.  
  1521.     drawneedle(inst->last_rot100[current], instrument_data.darkneedle,
  1522.            needle100);
  1523.     drawneedle(inst->last_rot1000[current], instrument_data.lightneedle,
  1524.            needle1000);
  1525.     inst->last_alt[current] = altitude;
  1526.     }
  1527.     popmatrix();
  1528. }
  1529.  
  1530. update_altimeter_ci(altimeter_t *inst, int forceupdate)
  1531. {
  1532.     static float lowstripes[16][3] = { -1.5,-4.5,0.0, -2.25,-4.5,0.0,
  1533.         -1.0,-3.25,0.0, -1.0,-4.0,0.0, -3.0,-4.5,0.0, -3.75,-4.5,0.0,
  1534.         -1.25,-2.0,0.0, -1.0,-2.5,0.0, -4.5,-4.5,0.0, -4.5,-3.75,0.0,
  1535.         -2.75,-2.0,0.0, -2.0,-2.0,0.0, -4.5,-3.0,0.0, -4.5,-2.0,0.0,
  1536.         -3.5,-2.0,0.0, -1.0,-2.0,0.0 };
  1537.     static float box10[4][3]  = { -4.5,-4.5,0.0, -1.0,-4.5,0.0, -1.0,-2.0,0.0,
  1538.         -4.5,-2.0,0.0 };
  1539.     static float boxt10[4][3] = { -4.5,-2.0,0.0, -1.0,-2.0,0.0, -1.0,.5,0.0,
  1540.         -4.5,.5,0.0 };
  1541.     static float boxb10[4][3] = { -4.5,-7.0,0.0, -1.0,-7.0,0.0, -1.0,-4.5,0.0,
  1542.         -4.5,-4.5,0.0 };
  1543.     static float needle1000[5][3] = {-.3,0.0,0.0, -.3,4.0,0.0, 0.0,5.0,0.0,
  1544.         .3,4.0,0.0, .3,0.0,0.0};
  1545.     static float needle100[5][3]  = {-.2,0.0,0.0, -.2,5.0,0.0, 0.0,7.0,0.0,
  1546.         .2,5.0,0.0, .2,0.0,0.0 };
  1547.     static float needle1000box[5][3] = {-.7,-.8,0.0, -.7,5.3,0.0, .7,5.3,0.0,
  1548.         .7,-.8,0.0 };
  1549.     static float needle100box[5][3]  = {-.6,-.3,0.0, -.6,7.3,0.0, .6,7.3,0.0,
  1550.         .6,-.3,0.0};
  1551.     static float cx= -3.5, cy= -3.7, cz=0.0; /* Pos of text for 10K ft. meter */
  1552.     int current;
  1553.     int new10= 0;
  1554.     int old10= 0;
  1555.     char buf[5];
  1556.     float alt1000;
  1557.     float altitude;
  1558.     Plane pp = planes[0];
  1559.  
  1560.     altitude = pp->y - plane_height;
  1561.  
  1562.     current = instrument_data.current;
  1563.     pushmatrix();
  1564.     translate(inst->px, inst->py, inst->pz);
  1565.     scale(inst->size, inst->size, inst->size);
  1566.     if ((altitude != inst->last_alt[current]) || forceupdate ||
  1567.         (inst->framec + inst->displayagain))
  1568.     {
  1569.     if (inst->displayagain) inst->displayagain--;
  1570.     color(ci_table[C_BLACK]);
  1571.     pushmatrix();
  1572.     rot(inst->last_rot1000[current], 'z');
  1573.     drawneedlebox(needle1000box);
  1574.     popmatrix();
  1575.     pushmatrix();
  1576.     rot(inst->last_rot100[current], 'z');
  1577.     drawneedlebox(needle100box);
  1578.     popmatrix();
  1579.     ICOLOR(instrument_data.textbackground);
  1580.     drawneedlebox(box10);
  1581.  
  1582.     new10 = (int)altitude/10000;
  1583.     old10 = (int)inst->last_alt[current]/10000;
  1584.     if ((new10 == 0)&&(old10 == 1))
  1585.     {
  1586.         inst->warningdown = -1;
  1587.         inst->warningup = 0;
  1588.         if (!inst->framec) inst->framec = inst->numframes;
  1589.     }
  1590.     else if ((new10 == 1)&&(old10 == 0))
  1591.     {
  1592.         inst->warningdown = 0;
  1593.         inst->warningup = 1;
  1594.         if (!inst->framec) inst->framec = 1;
  1595.     }
  1596.  
  1597.     if ((altitude < 10000) || (inst->warningup+inst->warningdown))
  1598.     {
  1599.         if (inst->framec)
  1600.         {
  1601.         pushmatrix();
  1602.  
  1603.         ICOLOR(instrument_data.text);
  1604.         cmov(cx, cy, cz);
  1605.         charstr("10");
  1606.         translate(0.0, inst->scale * inst->framec, 0.0);
  1607.         ICOLOR(instrument_data.textbackground);
  1608.         drawneedlebox(box10);
  1609.         }
  1610.         ICOLOR(instrument_data.yellow);
  1611.         bgnpolygon();
  1612.         v3f(lowstripes[0]);
  1613.         v3f(lowstripes[1]);
  1614.         v3f(lowstripes[2]);
  1615.         v3f(lowstripes[3]);
  1616.         endpolygon();
  1617.         bgnpolygon();
  1618.         v3f(lowstripes[4]);
  1619.         v3f(lowstripes[5]);
  1620.         v3f(lowstripes[6]);
  1621.         v3f(lowstripes[15]);
  1622.         v3f(lowstripes[7]);
  1623.         endpolygon();
  1624.         bgnpolygon();
  1625.         v3f(lowstripes[8]);
  1626.         v3f(lowstripes[9]);
  1627.         v3f(lowstripes[10]);
  1628.         v3f(lowstripes[11]);
  1629.         endpolygon();
  1630.         bgnpolygon();
  1631.         v3f(lowstripes[12]);
  1632.         v3f(lowstripes[13]);
  1633.         v3f(lowstripes[14]);
  1634.         endpolygon();
  1635.         if (inst->framec)
  1636.         {
  1637.         popmatrix();
  1638.         COLOR(C_BLACK);
  1639.         bgnpolygon();
  1640.         v3f(boxt10[0]);
  1641.         v3f(boxt10[1]);
  1642.         v3f(boxt10[2]);
  1643.         v3f(boxt10[3]);
  1644.         endpolygon();
  1645.         inst->framec = (inst->framec + inst->warningup
  1646.                 + inst->warningdown) % inst->numframes;
  1647.         if (!inst->framec)
  1648.         {
  1649.             inst->warningup = inst->warningdown = 0;
  1650.             inst->displayagain = 2;
  1651.         }
  1652.         }
  1653.     }
  1654.     else if ((alt1000=(10000.0-fmod(altitude, 10000.0))) <
  1655.          inst->scrollalt)
  1656.     {
  1657.         pushmatrix();
  1658.         ICOLOR(instrument_data.text);
  1659.         translate(0.0,(inst->scrollalt-alt1000)*inst->scale10,0.0);
  1660.         if (inst->old10 != new10)
  1661.         {
  1662.         sprintf(inst->low10str,"%d",new10*10);
  1663.         sprintf(inst->high10str,"%d",(new10+1)*10);
  1664.         }
  1665.         cmov(cx,cy,cz);
  1666.         charstr(inst->low10str);
  1667.         translate(0.0, -2.5, 0.0);
  1668.         cmov(cx,cy,cz);
  1669.         charstr(inst->high10str);
  1670.         popmatrix();
  1671.         COLOR(C_BLACK);
  1672.         drawneedlebox(boxt10);
  1673.         drawneedlebox(boxb10);
  1674.     }
  1675.     else
  1676.     {
  1677.         ICOLOR(instrument_data.text);
  1678.         sprintf(buf,"%d",new10*10);
  1679.         cmov(cx,cy,cz);
  1680.         charstr(buf);
  1681.     }
  1682.     ICOLOR(instrument_data.textborder);
  1683.     bgnclosedline();
  1684.     v3f(box10[0]);
  1685.     v3f(box10[1]);
  1686.     v3f(box10[2]);
  1687.     v3f(box10[3]);
  1688.     endclosedline();
  1689.     inst->last_rot1000[current]=(int)(fmod(altitude,10000.0)*-.036);
  1690.     inst->last_rot100[current] =(int)(fmod(altitude, 1000.0)*-.36);
  1691.  
  1692.     drawneedle(inst->last_rot100[current], instrument_data.darkneedle,
  1693.            needle100);
  1694.     drawneedle(inst->last_rot1000[current], instrument_data.lightneedle,
  1695.            needle1000);
  1696.     inst->last_alt[current] = altitude;
  1697.     }
  1698.     popmatrix();
  1699. }
  1700.  
  1701.  
  1702.  
  1703. /*
  1704.  * Initialize the altimeter's private data and add its functions to
  1705.  * the drawing lists
  1706.  */
  1707. void init_altimeter(float px, float py, float pz, float size)
  1708. {
  1709.     altimeter_t *inst;
  1710.  
  1711.     inst = (altimeter_t *)malloc(sizeof(*inst));
  1712.     bzero(inst, sizeof(*inst));
  1713.     inst->plateobject = plate1;
  1714.     inst->px = px;
  1715.     inst->py = py;
  1716.     inst->pz = pz;
  1717.     inst->size = size;
  1718.     inst->last_alt[1] = inst->last_alt[0] = -1.0;
  1719.     inst->last_rot1000[0] = inst->last_rot1000[1] = 0.0;
  1720.     inst->last_rot100[0] = inst->last_rot100[1] = 0.0;
  1721.     inst->framec = 0;
  1722.     inst->numframes = 20;
  1723.     inst->scale = 2.5 / inst->numframes;
  1724.     inst->scrollalt = 1000.0;
  1725.     inst->scale10 = 2.5 / inst->scrollalt;
  1726.     inst->warningup = inst->warningdown = 0;
  1727.     inst->old10 = 0;
  1728.     inst->high10str[0] = inst->low10str[0] = '\0';
  1729.  
  1730.     if (in_cmode)
  1731.     append_inst_list(draw_altimeter_ci, update_altimeter_ci, inst);
  1732.     else
  1733.     append_inst_list(draw_altimeter, update_altimeter, inst);
  1734. }
  1735.  
  1736.  
  1737. /************************************************************************
  1738. ***            Airspeed/machmeter indicator functions          ***
  1739. ************************************************************************/
  1740.  
  1741.  
  1742. typedef struct {
  1743.     float px, py, pz;        /* Position of instrument */
  1744.     float size;            /* Size of instrument */
  1745.     int last_speed[2];        /* Previous speed of both buffers */
  1746.     float last_rot[2];
  1747.     float last_machrot[2];
  1748.     object_t *plateobject;
  1749.     float stall_speed;
  1750.     float max_flaps;
  1751.     float max_speed;
  1752.     int machmeter;
  1753.     float maxmach;
  1754.     float machstep;
  1755.     int nummachticks;
  1756. } airspeedmach_t;
  1757.  
  1758.  
  1759.  
  1760. /*
  1761.  * Draw the airspeed indicator
  1762.  */
  1763. draw_airspeedmach(airspeedmach_t *inst)
  1764. {
  1765.     static float verts[4][3] = { -9.0,-9.0,0.0, -9.0,9.0,0.0, 9.0,9.0,0.0,
  1766.             9.0,-9.0,0.0 };
  1767.     static float ticks[2][3]      = { 0.0,8.0,0.0, 0.0,9.0,0.0 };
  1768.     static float smallticks[2][3] = { 0.0,8.3,0.0, 0.0,9.0,0.0 };
  1769.     static float machticks[2][3]  = { 0.0,4.5,0.0, 0.0,5.5,0.0 };
  1770.     static float machtinyticks[2][3] = { 0.0,5.0,0.0, 0.0,5.5,0.0 };
  1771.     short sl, sr, sb, st;
  1772.     int numberstep;
  1773.     float bigtickstep, numbertickstep, smalltickstep, tinytickstep;
  1774.     float machtickstep, machtinytickstep, machtinystep;
  1775.     float mach;
  1776.     int x;
  1777.     char buf[5];
  1778.  
  1779.     pushmatrix();
  1780.     translate(inst->px, inst->py, inst->pz);
  1781.     scale(inst->size, inst->size, inst->size);
  1782.     if (!in_cmode)
  1783.     {
  1784.     drawmode(UNDERDRAW);
  1785.     color(U_INST);
  1786.     clear_inst1();
  1787.     color(MARKINGS);
  1788.     }
  1789.     else
  1790.     {
  1791.     drawmode(PUPDRAW);
  1792.     color(U_BLACK);
  1793.     clear_inst1();
  1794.     color(P_MARKINGS);
  1795.     }
  1796.  
  1797.     bigtickstep = -30000.0 / inst->max_speed;
  1798.     numbertickstep = bigtickstep;
  1799.     if (inst->max_speed <= 300.0)
  1800.     {
  1801.     numberstep = 50;
  1802.     numbertickstep /= 2.0;
  1803.     }
  1804.     else
  1805.     numberstep = 100;
  1806.  
  1807.     smalltickstep = -6000.0 / inst->max_speed;
  1808.     tinytickstep = -3000.0 / inst->max_speed;
  1809.  
  1810.     pushmatrix();
  1811.     rot(-30.0,'z');
  1812.     for (x=0; x <= (int)inst->max_speed; x+= numberstep)
  1813.     {
  1814.     bgnline();
  1815.     v3f(ticks[0]);
  1816.     v3f(ticks[1]);
  1817.     endline();
  1818.     rot(numbertickstep,'z');
  1819.     }
  1820.     popmatrix();
  1821.     pushmatrix();
  1822.     pushviewport();
  1823.     getviewport(&sl,&sr,&sb,&st);
  1824.     viewport(sl-instrument_data.threewide, sr-instrument_data.threewide,
  1825.          sb-instrument_data.chartall, st-instrument_data.chartall);
  1826.     cmov(0.0,1.2,0.0);
  1827.     charstr("KTS");
  1828.     popviewport();
  1829.     pushviewport();
  1830.     viewport(sl-instrument_data.fourwide, sr-instrument_data.fourwide,
  1831.          sb-instrument_data.chartall, st-instrument_data.chartall);
  1832.     cmov(0.0,-1.2,0.0);
  1833.     charstr("MACH");
  1834.     popviewport();
  1835.     pushviewport();
  1836.     rot(-30.0,'z');
  1837.     viewport(sl-instrument_data.threewide, sr-instrument_data.threewide,
  1838.         sb-instrument_data.chartall, st-instrument_data.chartall);
  1839.     for (x=0; x <= (int)inst->max_speed; x+= numberstep)
  1840.     {
  1841.     cmov(0.0, 6.8, 0.0);
  1842.     sprintf(buf,"%d",x);
  1843.     charstr(buf);
  1844.     rot(numbertickstep,'z');
  1845.     }
  1846.     popviewport();
  1847.     popmatrix();
  1848.     pushmatrix();
  1849.     rot(-30.0, 'z');
  1850.     for (x=0; (x < 300) && (x <= inst->max_speed); x += 10)
  1851.     {
  1852.     if (x%numberstep)
  1853.     {
  1854.         bgnline();
  1855.         v3f(smallticks[0]);
  1856.         v3f(smallticks[1]);
  1857.         endline();
  1858.     }
  1859.     rot(tinytickstep, 'z');
  1860.     }
  1861.     for (x=300; x <= inst->max_speed; x += 20)
  1862.     {
  1863.     if (x%100)
  1864.     {
  1865.         bgnline();
  1866.         v3f(smallticks[0]);
  1867.         v3f(smallticks[1]);
  1868.         endline();
  1869.     }
  1870.     rot(smalltickstep, 'z');
  1871.     }
  1872.     popmatrix();
  1873.     machtickstep = -300.0 * inst->machstep / inst->maxmach;
  1874.     machtinytickstep = machtickstep / inst->nummachticks;
  1875.     machtinystep = inst->machstep /
  1876.                 (float) inst->nummachticks;
  1877.     if (inst->machmeter)
  1878.     {
  1879.     pushmatrix();
  1880.     rot(-30.0, 'z');
  1881.     for (mach=0.0; mach <= inst->maxmach;
  1882.          mach += inst->machstep)
  1883.     {
  1884.         bgnline();
  1885.         v3f(machticks[0]);
  1886.         v3f(machticks[1]);
  1887.         endline();
  1888.         rot(machtickstep, 'z');
  1889.     }
  1890.     popmatrix();
  1891.     pushmatrix();
  1892.     rot(-30.0, 'z');
  1893.     for (mach=0.0; mach < inst->maxmach;
  1894.          mach += inst->machstep)
  1895.     {
  1896.         rot(machtinytickstep, 'z');
  1897.         for (x=1; x < inst->nummachticks; x++)
  1898.         {
  1899.         bgnline();
  1900.         v3f(machtinyticks[0]);
  1901.         v3f(machtinyticks[1]);
  1902.         endline();
  1903.         rot(machtinytickstep, 'z');
  1904.         }
  1905.     }
  1906.     popmatrix();
  1907.     pushviewport();
  1908.     pushmatrix();
  1909.     rot(-30.0, 'z');
  1910.     viewport(sl-instrument_data.threewide, sr-instrument_data.threewide,
  1911.         sb-instrument_data.chartall, st-instrument_data.chartall);
  1912.     for (mach=0.0; mach <= inst->maxmach; mach +=
  1913.                     inst->machstep)
  1914.     {
  1915.         cmov(0.0, 3.2, 0.0);
  1916.         sprintf(buf,"%3.1f",mach);
  1917.         charstr(buf);
  1918.         rot(machtickstep, 'z');
  1919.     }
  1920.     popviewport();
  1921.     popmatrix();
  1922.     }
  1923.  
  1924.     drawmode(NORMALDRAW);
  1925.     frontbuffer(TRUE);
  1926.  
  1927.     COLOR(C_BLACK);
  1928.     clear_inst1();
  1929.  
  1930.     draw_plate(inst->plateobject, 0x3);
  1931.  
  1932.     frontbuffer(FALSE);
  1933.     popmatrix();
  1934. }
  1935.  
  1936.  
  1937. update_airspeedmach(airspeedmach_t *inst, int forceupdate)
  1938. {
  1939.     static float needle[5][3] = {-.2,0.0,0.0, -.2,5.5,0.0, 0.0,7.0,0.0,
  1940.             .2,5.5,0.0, .2,0.0,0.0};
  1941.     static float needlebox[5][3] = {-.7,-.8,0.0, -.7,7.5,0.0, .7,7.5,0.0,
  1942.             .7,-.8,0.0 };
  1943.     static float machneedle[5][3] = {-.2,0.0,0.0, -.2,2.8,0.0, 0.0,4.2,0.0,
  1944.             .2,2.8,0.0, .2,0.0,0.0};
  1945.     static float machneedlebox[5][3] = {-.7,-.8,0.0, -.7,4.8,0.0, .7,4.8,0.0,
  1946.             .7,-.8,0.0 };
  1947.     int current;
  1948.     static float machone = 700.0;
  1949.     current = instrument_data.current;
  1950.  
  1951.     pushmatrix();
  1952.     translate(inst->px, inst->py, inst->pz);
  1953.     scale(inst->size, inst->size, inst->size);
  1954.     if ((airspeed != inst->last_speed[current]) || forceupdate)
  1955.     {
  1956.     COLOR(C_BLACK);
  1957.     pushmatrix();
  1958.     rot(inst->last_rot[current], 'z');
  1959.     drawneedlebox(needlebox);
  1960.     popmatrix();
  1961.     pushmatrix();
  1962.     rot(inst->last_machrot[current], 'z');
  1963.     drawneedlebox(machneedlebox);
  1964.     popmatrix();
  1965. #ifndef NO_MS
  1966.     if (ms_samples)
  1967.     {
  1968.         pushmatrix();
  1969.         rot(inst->last_rot[!current], 'z');
  1970.         drawneedlebox(needlebox);
  1971.         popmatrix();
  1972.         pushmatrix();
  1973.         rot(inst->last_machrot[!current], 'z');
  1974.         drawneedlebox(machneedlebox);
  1975.         popmatrix();
  1976.     }
  1977. #endif
  1978.  
  1979.     inst->last_rot[current] = -300.0 * airspeed / inst->max_speed - 30.0;
  1980.     if (inst->last_rot[current] < -330.0)
  1981.         inst->last_rot[current] = -330.0;
  1982.     else if (inst->last_rot[current] > -30.0)
  1983.         inst->last_rot[current] = -30.0;
  1984.     inst->last_machrot[current] = -300 * airspeed /
  1985.                 ( inst->maxmach * machone ) - 30.0;
  1986.     if (inst->last_machrot[current] < -330.0)
  1987.         inst->last_machrot[current] = -330.0;
  1988.     else if (inst->last_machrot[current] > -30.0)
  1989.         inst->last_machrot[current] = -30.0;
  1990.  
  1991.     drawneedle(inst->last_machrot[current],
  1992.            instrument_data.darkneedle, machneedle);
  1993.     drawneedle(inst->last_rot[current],
  1994.            instrument_data.lightneedle, needle);
  1995.     }
  1996.     popmatrix();
  1997. }
  1998.  
  1999.  
  2000.  
  2001. void init_airspeedmach(float px, float py, float pz, float size,
  2002.                  float maxspeed, int machmeter, float maxmach,
  2003.                  float machstep, int nummachticks)
  2004. {
  2005.     airspeedmach_t *inst;
  2006.  
  2007.     inst = (airspeedmach_t *)malloc(sizeof(*inst));
  2008.     bzero(inst, sizeof(*inst));
  2009.     inst->plateobject = plate1;
  2010.     inst->px = px;
  2011.     inst->py = py;
  2012.     inst->pz = pz;
  2013.     inst->size = size;
  2014.     inst->max_speed = maxspeed;
  2015.     inst->last_speed[1] = inst->last_speed[0] = airspeed + 1.0;
  2016.     inst->machmeter = machmeter;
  2017.     inst->maxmach = maxmach;
  2018.     inst->machstep = machstep;
  2019.     inst->nummachticks = nummachticks;
  2020.     append_inst_list(draw_airspeedmach, update_airspeedmach, inst);
  2021. }
  2022.  
  2023.  
  2024. /************************************************************************
  2025. ***            Airspeed indicator functions             ****
  2026. ************************************************************************/
  2027.  
  2028.  
  2029. typedef struct {
  2030.     float px, py, pz;        /* Position of instrument */
  2031.     float size;            /* Size of instrument */
  2032.     object_t *plateobject;
  2033.     int last_speed[2];        /* Previous speed of both buffers */
  2034.     float last_rot[2];
  2035.     float stall_speed;
  2036.     float max_flaps;
  2037.     float max_speed;
  2038. } airspeed_meter_t;
  2039.  
  2040.  
  2041. /*
  2042.  * Draw the airspeed indicator
  2043.  */
  2044. draw_airspeed_meter(airspeed_meter_t *inst)
  2045. {
  2046.     static float verts[4][3] = { -9.0,-9.0,0.0, -9.0,9.0,0.0, 9.0,9.0,0.0,
  2047.             9.0,-9.0,0.0 };
  2048.     static float ticks[2][3]      = { 0.0,8.0,0.0, 0.0,9.0,0.0 };
  2049.     static float smallticks[2][3] = { 0.0,8.3,0.0, 0.0,9.0,0.0 };
  2050.     short sl, sr, sb, st;
  2051.     int numberstep;
  2052.     float bigtickstep, numbertickstep, smalltickstep, tinytickstep;
  2053.     int x;
  2054.     char buf[5];
  2055.  
  2056.     pushmatrix();
  2057.     translate(inst->px, inst->py, inst->pz);
  2058.     scale(inst->size, inst->size, inst->size);
  2059.  
  2060.     if (!in_cmode)
  2061.     {
  2062.     drawmode(UNDERDRAW);
  2063.     color(U_INST);
  2064.     clear_inst1();
  2065.     color(MARKINGS);
  2066.     }
  2067.     else
  2068.     {
  2069.     drawmode(PUPDRAW);
  2070.     color(U_BLACK);
  2071.     clear_inst1();
  2072.     color(P_MARKINGS);
  2073.     }
  2074.  
  2075.     bigtickstep = -30000.0 / inst->max_speed;
  2076.     numbertickstep = bigtickstep;
  2077.     if (inst->max_speed <= 300.0)
  2078.     {
  2079.     numberstep = 50;
  2080.     numbertickstep /= 2.0;
  2081.     }
  2082.     else
  2083.     numberstep = 100;
  2084.  
  2085.     smalltickstep = -6000.0 / inst->max_speed;
  2086.     tinytickstep = -3000.0 / inst->max_speed;
  2087.  
  2088.     pushmatrix();
  2089.     rot(-30.0,'z');
  2090.     for (x=0; x <= (int)inst->max_speed; x+= numberstep)
  2091.     {
  2092.     bgnline();
  2093.     v3f(ticks[0]);
  2094.     v3f(ticks[1]);
  2095.     endline();
  2096.     rot(numbertickstep,'z');
  2097.     }
  2098.     popmatrix();
  2099.     pushmatrix();
  2100.     pushviewport();
  2101.     getviewport(&sl,&sr,&sb,&st);
  2102.     viewport(sl-instrument_data.threewide, sr-instrument_data.threewide,
  2103.          sb-instrument_data.chartall, st-instrument_data.chartall);
  2104.     cmov(0.0,-4.0,0.0);
  2105.     charstr("KTS");
  2106.     popviewport();
  2107.     pushviewport();
  2108.     rot(-30.0,'z');
  2109.     viewport(sl-instrument_data.threewide, sr-instrument_data.threewide,
  2110.         sb-instrument_data.chartall, st-instrument_data.chartall);
  2111.     for (x=0; x <= (int)inst->max_speed; x+= numberstep)
  2112.     {
  2113.     cmov(0.0, 6.8, 0.0);
  2114.     sprintf(buf,"%d",x);
  2115.     charstr(buf);
  2116.     rot(numbertickstep,'z');
  2117.     }
  2118.     popviewport();
  2119.     popmatrix();
  2120.     pushmatrix();
  2121.     rot(-30.0, 'z');
  2122.     for (x=0; (x < 300) && (x <= inst->max_speed); x += 10)
  2123.     {
  2124.     if (x%numberstep)
  2125.     {
  2126.         bgnline();
  2127.         v3f(smallticks[0]);
  2128.         v3f(smallticks[1]);
  2129.         endline();
  2130.     }
  2131.     rot(tinytickstep, 'z');
  2132.     }
  2133.     for (x=300; x <= inst->max_speed; x += 20)
  2134.     {
  2135.     if (x%100)
  2136.     {
  2137.         bgnline();
  2138.         v3f(smallticks[0]);
  2139.         v3f(smallticks[1]);
  2140.         endline();
  2141.     }
  2142.     rot(smalltickstep, 'z');
  2143.     }
  2144.     popmatrix();
  2145.  
  2146.     drawmode(NORMALDRAW);
  2147.     frontbuffer(TRUE);
  2148.  
  2149.     COLOR(C_BLACK);
  2150.     clear_inst1();
  2151.  
  2152.     draw_plate(inst->plateobject, 0x3);
  2153.  
  2154.     frontbuffer(FALSE);
  2155.     popmatrix();
  2156. }
  2157.  
  2158.  
  2159. update_airspeed_meter(airspeed_meter_t *inst, int forceupdate)
  2160. {
  2161.     static float needle[5][3] = {-.2,0.0,0.0, -.2,5.5,0.0, 0.0,7.0,0.0,
  2162.             .2,5.5,0.0, .2,0.0,0.0};
  2163.     static float needlebox[5][3] = {-.7,-.8,0.0, -.7,7.5,0.0, .7,7.5,0.0,
  2164.             .7,-.8,0.0 };
  2165.     int current;
  2166.  
  2167.     current = instrument_data.current;
  2168.  
  2169.     pushmatrix();
  2170.     translate(inst->px, inst->py, inst->pz);
  2171.     scale(inst->size, inst->size, inst->size);
  2172.     if ((airspeed != inst->last_speed[current]) || forceupdate)
  2173.     {
  2174.     COLOR(C_BLACK);
  2175.     pushmatrix();
  2176.     rot(inst->last_rot[current], 'z');
  2177.     drawneedlebox(needlebox);
  2178.     popmatrix();
  2179. #ifndef NO_MS
  2180.     if (ms_samples)
  2181.     {
  2182.         pushmatrix();
  2183.         rot(inst->last_rot[!current], 'z');
  2184.         drawneedlebox(needlebox);
  2185.         popmatrix();
  2186.     }
  2187. #endif
  2188.  
  2189.     inst->last_rot[current] = -300.0 * airspeed /
  2190.                 inst->max_speed - 30.0;
  2191.     if (inst->last_rot[current] < -330.0)
  2192.         inst->last_rot[current] = -330.0;
  2193.     else if (inst->last_rot[current] > -30.0)
  2194.         inst->last_rot[current] = -30.0;
  2195.  
  2196.     drawneedle(inst->last_rot[current], instrument_data.lightneedle,
  2197.            needle);
  2198.     }
  2199.     popmatrix();
  2200. }
  2201.  
  2202.  
  2203.  
  2204. void init_airspeed_meter(float px, float py, float pz, float size,
  2205.              float maxspeed)
  2206. {
  2207.     airspeed_meter_t *inst;
  2208.  
  2209.     inst = (airspeed_meter_t *)malloc(sizeof(*inst));
  2210.     bzero(inst, sizeof(*inst));
  2211.     inst->px = px;
  2212.     inst->py = py;
  2213.     inst->pz = pz;
  2214.     inst->size = size;
  2215.     inst->plateobject = plate1;
  2216.     inst->max_speed = maxspeed;
  2217.     inst->last_speed[1] = inst->last_speed[0] = airspeed + 1.0;
  2218.  
  2219.     append_inst_list(draw_airspeed_meter, update_airspeed_meter, inst);
  2220. }
  2221.  
  2222.  
  2223. /************************************************************************
  2224. ***            Mach indicator functions             ****
  2225. ************************************************************************/
  2226.  
  2227.  
  2228. typedef struct {
  2229.     float px, py, pz;        /* Position of instrument */
  2230.     float size;            /* Size of instrument */
  2231.     object_t *plateobject;
  2232.     int last_speed[2];        /* Previous speed of both buffers */
  2233.     float last_machrot[2];
  2234.     float maxmach;
  2235.     float machstep;
  2236.     int nummachticks;
  2237. } mach_meter_t;
  2238.  
  2239.  
  2240.  
  2241. /*
  2242.  * Draw the mach indicator
  2243.  */
  2244. draw_mach_meter(mach_meter_t *inst)
  2245. {
  2246.     static float verts[4][3] = { -9.0,-9.0,0.0, -9.0,9.0,0.0, 9.0,9.0,0.0,
  2247.             9.0,-9.0,0.0 };
  2248.     static float machticks[2][3]      = { 0.0,7.85,0.0, 0.0,9.0,0.0 };
  2249.     static float machtinyticks[2][3] = { 0.0,8.2,0.0, 0.0,9.0,0.0 };
  2250.     short sl, sr, sb, st;
  2251.     int numberstep;
  2252.     float machtickstep, machtinytickstep;
  2253.     float mach;
  2254.     int x;
  2255.     char buf[5];
  2256.  
  2257.     pushmatrix();
  2258.     translate(inst->px, inst->py, inst->pz);
  2259.     scale(inst->size, inst->size, inst->size);
  2260.     if (!in_cmode)
  2261.     {
  2262.     drawmode(UNDERDRAW);
  2263.     color(U_INST);
  2264.     clear_inst1();
  2265.     color(MARKINGS);
  2266.     }
  2267.     else
  2268.     {
  2269.     drawmode(PUPDRAW);
  2270.     color(U_BLACK);
  2271.     clear_inst1();
  2272.     color(P_MARKINGS);
  2273.     }
  2274.  
  2275.     pushviewport();
  2276.     viewport(sl-instrument_data.fourwide, sr-instrument_data.fourwide,
  2277.          sb-instrument_data.chartall, st-instrument_data.chartall);
  2278.     cmov(0.0,-4.0,0.0);
  2279.     charstr("MACH");
  2280.     popviewport();
  2281.  
  2282.     machtickstep = -300.0 * inst->machstep / (inst->maxmach - 1.0);
  2283.  
  2284.     machtinytickstep = machtickstep / inst->nummachticks;
  2285.     pushmatrix();
  2286.     rot(-30.0, 'z');
  2287.     for (mach=1.0; mach <= inst->maxmach; mach += inst->machstep)
  2288.     {
  2289.     bgnline();
  2290.     v3f(machticks[0]);
  2291.     v3f(machticks[1]);
  2292.     endline();
  2293.     rot(machtickstep, 'z');
  2294.     }
  2295.     popmatrix();
  2296.     pushmatrix();
  2297.     rot(-30.0, 'z');
  2298.     for (mach=1.0; mach < inst->maxmach; mach +=
  2299.                 inst->machstep)
  2300.     {
  2301.     rot(machtinytickstep, 'z');
  2302.     for (x=1; x < inst->nummachticks; x++)
  2303.     {
  2304.         bgnline();
  2305.         v3f(machtinyticks[0]);
  2306.         v3f(machtinyticks[1]);
  2307.         endline();
  2308.         rot(machtinytickstep, 'z');
  2309.     }
  2310.     }
  2311.     popmatrix();
  2312.     pushviewport();
  2313.     pushmatrix();
  2314.     rot(-30.0, 'z');
  2315.     viewport(sl-instrument_data.threewide, sr-instrument_data.threewide,
  2316.            sb-instrument_data.chartall, st-instrument_data.chartall);
  2317.     for (mach=1.0; mach <= inst->maxmach; mach +=
  2318.                 inst->machstep)
  2319.     {
  2320.     cmov(0.0, 6.5, 0.0);
  2321.     sprintf(buf,"%3.1f",mach);
  2322.     charstr(buf);
  2323.     rot(machtickstep, 'z');
  2324.     }
  2325.     popviewport();
  2326.     popmatrix();
  2327.  
  2328.     drawmode(NORMALDRAW);
  2329.     frontbuffer(TRUE);
  2330.  
  2331.     COLOR(C_BLACK);
  2332.     clear_inst1();
  2333.  
  2334.     draw_plate(inst->plateobject, 0x3);
  2335.  
  2336.     frontbuffer(FALSE);
  2337.     popmatrix();
  2338. }
  2339.  
  2340.  
  2341. update_mach_meter(mach_meter_t *inst, int forceupdate)
  2342. {
  2343.     static float machneedle[5][3] = {-.2,0.0,0.0, -.2,5.5,0.0, 0.0,7.0,0.0,
  2344.             .2,5.5,0.0, .2,0.0,0.0};
  2345.     static float machneedlebox[5][3] = {-.7,-.8,0.0, -.7,7.5,0.0, .7,7.5,0.0,
  2346.             .7,-.8,0.0 };
  2347.     int current;
  2348.     static float machone = 700.0;
  2349.  
  2350.     current = instrument_data.current;
  2351.  
  2352.     pushmatrix();
  2353.     translate(inst->px, inst->py, inst->pz);
  2354.     scale(inst->size, inst->size, inst->size);
  2355.     if ((airspeed != inst->last_speed[current]) || forceupdate)
  2356.     {
  2357.     COLOR(C_BLACK);
  2358.     pushmatrix();
  2359.     rot(inst->last_machrot[current], 'z');
  2360.     drawneedlebox(machneedlebox);
  2361.     popmatrix();
  2362. #ifndef NO_MS
  2363.     if (ms_samples)
  2364.     {
  2365.         pushmatrix();
  2366.         rot(inst->last_machrot[!current], 'z');
  2367.         drawneedlebox(machneedlebox);
  2368.         popmatrix();
  2369.     }
  2370. #endif
  2371.  
  2372.     inst->last_machrot[current] = -300 * (airspeed - 700.0)  /
  2373.                 ( inst->maxmach * machone ) - 30.0;
  2374.     if (inst->last_machrot[current] < -330.0)
  2375.         inst->last_machrot[current] = -330.0;
  2376.     else if (inst->last_machrot[current] > -22.0)
  2377.         inst->last_machrot[current] = -22.0;
  2378.  
  2379.     drawneedle(inst->last_machrot[current], instrument_data.darkneedle,
  2380.            machneedle);
  2381.     }
  2382.     popmatrix();
  2383. }
  2384.  
  2385.  
  2386.  
  2387. void init_mach_meter(float px, float py, float pz, float size,
  2388.              float maxmach, float machstep, int nummachticks)
  2389. {
  2390.     mach_meter_t *inst;
  2391.  
  2392.     inst = (mach_meter_t *)malloc(sizeof(*inst));
  2393.     bzero(inst, sizeof(*inst));
  2394.     inst->px = px;
  2395.     inst->py = py;
  2396.     inst->pz = pz;
  2397.     inst->size = size;
  2398.     inst->plateobject = plate1;
  2399.     inst->last_speed[1] = inst->last_speed[0] = airspeed + 1.0;
  2400.     inst->maxmach = maxmach;
  2401.     inst->machstep = machstep;
  2402.     inst->nummachticks =  nummachticks;
  2403.  
  2404.     append_inst_list(draw_mach_meter, update_mach_meter, inst);
  2405. }
  2406.  
  2407.  
  2408. /************************************************************************
  2409. ***        Vertical Velocity indicator functions              ***
  2410. ************************************************************************/
  2411.  
  2412.  
  2413. typedef struct {
  2414.     float px, py, pz;        /* Position of instrument */
  2415.     float size;            /* Size of instrument */
  2416.     object_t *plateobject;
  2417.     float last_vel[2];        /* Previous speed of both buffers */
  2418.     float last_rot[2];
  2419.     float max_vertvel;
  2420.     float min_vertvel;
  2421.     float divisions;
  2422.     int numsmallticks;
  2423. } vertvel_meter_t;
  2424.  
  2425.  
  2426.  
  2427. /*
  2428.  * Draw the airspeed indicator
  2429.  */
  2430. draw_vertvel_meter(vertvel_meter_t *inst)
  2431. {
  2432.     static float verts[4][3] = { -9.0,-9.0,0.0, -9.0,9.0,0.0, 9.0,9.0,0.0,
  2433.             9.0,-9.0,0.0 };
  2434.     static float ticks[2][3]      = { 0.0,7.7,0.0, 0.0,9.0,0.0 };
  2435.     static float smallticks[2][3] = { 0.0,8.2,0.0, 0.0,9.0,0.0 };
  2436.     short sl, sr, sb, st;
  2437.     float bigtickstep, smalltickstep;
  2438.     float smalldivision;
  2439.     float vel;
  2440.     char buf[5];
  2441.  
  2442.     pushmatrix();
  2443.     translate(inst->px, inst->py, inst->pz);
  2444.     scale(inst->size, inst->size, inst->size);
  2445.  
  2446.     if (!in_cmode)
  2447.     {
  2448.     drawmode(UNDERDRAW);
  2449.     color(U_INST);
  2450.     clear_inst1();
  2451.     color(MARKINGS);
  2452.     }
  2453.     else
  2454.     {
  2455.     drawmode(PUPDRAW);
  2456.     color(U_BLACK);
  2457.     clear_inst1();
  2458.     color(P_MARKINGS);
  2459.     }
  2460.  
  2461.     bigtickstep = -150.0 * inst->divisions / inst->max_vertvel;
  2462.     smalltickstep = bigtickstep / (float) inst->numsmallticks;
  2463.     smalldivision = inst->divisions / (float) inst->numsmallticks;
  2464.  
  2465.     pushviewport();
  2466.     getviewport(&sl,&sr,&sb,&st);
  2467.     viewport(sl-instrument_data.fivewide, sr-instrument_data.fivewide,
  2468.          sb-instrument_data.chartall, st-instrument_data.chartall);
  2469.     cmov(0.0,-2.5,0.0);
  2470.     charstr("CLIMB");
  2471.     popviewport();
  2472.     pushmatrix();
  2473.     rot(90.0,'z');
  2474.     pushmatrix();
  2475.     for (vel=0.0; vel <= inst->max_vertvel; vel += inst->divisions)
  2476.     {
  2477.     bgnline();
  2478.     v3f(ticks[0]);
  2479.     v3f(ticks[1]);
  2480.     endline();
  2481.     rot(bigtickstep,'z');
  2482.     }
  2483.     popmatrix();
  2484.     pushmatrix();
  2485.     for (vel=0.0; vel <= inst->max_vertvel; vel += inst->divisions)
  2486.     {
  2487.     bgnline();
  2488.     v3f(ticks[0]);
  2489.     v3f(ticks[1]);
  2490.     endline();
  2491.     rot(-bigtickstep,'z');
  2492.     }
  2493.     popmatrix();
  2494.     pushviewport();
  2495.     viewport(sl-instrument_data.fourwide, sr-instrument_data.fourwide,
  2496.         sb-instrument_data.chartall, st-instrument_data.chartall);
  2497.     pushmatrix();
  2498.     for (vel=0.0; vel <= inst->max_vertvel; vel += inst->divisions)
  2499.     {
  2500.     cmov(0.0, 6.2, 0.0);
  2501.     sprintf(buf,"%d",(int)vel);
  2502.     charstr(buf);
  2503.     rot(bigtickstep,'z');
  2504.     }
  2505.     popmatrix();
  2506.     pushmatrix();
  2507.     for (vel=0.0; vel <= inst->max_vertvel; vel += inst->divisions)
  2508.     {
  2509.     cmov(0.0, 6.2, 0.0);
  2510.     sprintf(buf,"%d",(int)vel);
  2511.     charstr(buf);
  2512.     rot(-bigtickstep,'z');
  2513.     }
  2514.     popmatrix();
  2515.     popviewport();
  2516.     pushmatrix();
  2517.     for (vel=0.0; vel <= inst->max_vertvel; vel += smalldivision)
  2518.     {
  2519.     if (fmod(vel, inst->divisions))
  2520.     {
  2521.         bgnline();
  2522.         v3f(smallticks[0]);
  2523.         v3f(smallticks[1]);
  2524.         endline();
  2525.     }
  2526.     rot(-smalltickstep, 'z');
  2527.     }
  2528.     popmatrix();
  2529.     pushmatrix();
  2530.     for (vel=0.0; vel <= inst->max_vertvel; vel += smalldivision)
  2531.     {
  2532.     if (fmod(vel, inst->divisions))
  2533.     {
  2534.         bgnline();
  2535.         v3f(smallticks[0]);
  2536.         v3f(smallticks[1]);
  2537.         endline();
  2538.     }
  2539.     rot(smalltickstep, 'z');
  2540.     }
  2541.     popmatrix();
  2542.     popmatrix();
  2543.     drawmode(NORMALDRAW);
  2544.     frontbuffer(TRUE);
  2545.  
  2546.     COLOR(C_BLACK);
  2547.     clear_inst1();
  2548.  
  2549.     draw_plate(inst->plateobject, 0x3);
  2550.  
  2551.     frontbuffer(FALSE);
  2552.     popmatrix();
  2553. }
  2554.  
  2555.  
  2556.  
  2557. update_vertvel_meter(vertvel_meter_t *inst, int forceupdate)
  2558. {
  2559.     static float needle[5][3] = {-.2,0.0,0.0, -.2,5.0,0.0, 0.0,6.5,0.0,
  2560.             .2,5.0,0.0, .2,0.0,0.0};
  2561.     static float needlebox[4][3] = {-.8,-.8,0.0, -.8,6.9,0.0, .8,6.9,0.0,
  2562.             .8,-.8,0.0 };
  2563.     int current;
  2564.     float vertvelocity;
  2565.  
  2566.     current = instrument_data.current;
  2567.  
  2568.     pushmatrix();
  2569.     translate(inst->px, inst->py, inst->pz);
  2570.     scale(inst->size, inst->size, inst->size);
  2571.  
  2572.     vertvelocity = climbspeed * 60;
  2573.  
  2574.     if ((vertvelocity != inst->last_vel[current]) || forceupdate)
  2575.     {
  2576.     COLOR(C_BLACK);
  2577.     pushmatrix();
  2578.     rot(inst->last_rot[current], 'z');
  2579.     drawneedlebox(needlebox);
  2580.     popmatrix();
  2581. #ifndef NO_MS
  2582.     if (ms_samples)
  2583.     {
  2584.         pushmatrix();
  2585.         rot(inst->last_rot[!current], 'z');
  2586.         drawneedlebox(needlebox);
  2587.         popmatrix();
  2588.     }
  2589. #endif
  2590.  
  2591.     if (vertvelocity > inst->max_vertvel)
  2592.         inst->last_rot[current] = -60.0;
  2593.     else if (vertvelocity < inst->min_vertvel)
  2594.         inst->last_rot[current] = 240.0;
  2595.     else
  2596.         inst->last_rot[current] = 90.0 + -150.0 * vertvelocity /
  2597.                       inst->max_vertvel;
  2598.     drawneedle(inst->last_rot[current], instrument_data.darkneedle,
  2599.            needle);
  2600.     }
  2601.     popmatrix();
  2602. }
  2603.  
  2604.  
  2605.  
  2606. void init_vertvel_meter(float px, float py, float pz, float size,
  2607.             float maxvel, float divisions, int numsmallticks)
  2608. {
  2609.     vertvel_meter_t *inst;
  2610.  
  2611.     inst = (vertvel_meter_t *)malloc(sizeof(*inst));
  2612.     bzero(inst, sizeof(*inst));
  2613.     inst->px = px;
  2614.     inst->py = py;
  2615.     inst->pz = pz;
  2616.     inst->size = size;
  2617.     inst->plateobject = plate1;
  2618.     inst->max_vertvel = maxvel;
  2619.     inst->min_vertvel = -1.0*maxvel;
  2620.     inst->divisions = divisions;
  2621.     inst->numsmallticks = numsmallticks;
  2622.     inst->last_vel[1] = inst->last_vel[0] = 1.0;
  2623.     append_inst_list(draw_vertvel_meter, update_vertvel_meter, inst);
  2624. }
  2625.  
  2626.  
  2627. /************************************************************************
  2628. ***            radar/compass functions                  ***
  2629. ************************************************************************/
  2630.  
  2631.  
  2632. typedef struct {
  2633.     float px, py, pz;        /* Position of instrument */
  2634.     float size;            /* Size of instrument */
  2635.     short sm_l, sm_r, sm_b, sm_t;
  2636.     object_t *plateobject;
  2637.     float ticks[72][2];
  2638. } radar_t;
  2639.  
  2640.  
  2641.  
  2642. /*
  2643.  * Draw the radar
  2644.  */
  2645. draw_radar(radar_t *inst)
  2646. {
  2647.     static float plane[13][3] =  {{ 0.0,  0.0}, { 0.2, -1.0}, { 1.2, -1.8},
  2648.                   { 1.2, -2.0}, { 0.2, -1.4}, { 0.2, -2.0},
  2649.                   { 0.5, -2.3}, {-0.5, -2.3}, {-0.2, -2.0},
  2650.                   {-0.2, -1.4}, {-1.2, -2.0}, {-1.2, -1.8},
  2651.                   {-0.2, -1.0}};
  2652.     long ox, oy;
  2653.  
  2654.     pushmatrix();
  2655.     translate(inst->px, inst->py, inst->pz);
  2656.     scale(inst->size, inst->size, inst->size);
  2657.  
  2658.     /*
  2659.      *  get instoment screen mask
  2660.      */
  2661.     cmov2i(-9.0, -9.0);
  2662.     getcpos(&inst->sm_l, &inst->sm_b);
  2663.     cmov2i(9.0, 9.0);
  2664.     getcpos(&inst->sm_r, &inst->sm_t);
  2665.     getorigin(&ox, &oy);
  2666.     inst->sm_l -= ox;
  2667.     inst->sm_r -= ox;
  2668.     inst->sm_b -= oy;
  2669.     inst->sm_t -= oy;
  2670.  
  2671.     drawmode(PUPDRAW);
  2672.  
  2673.     pushmatrix();
  2674.     scale(0.9, 0.9, 0.9);
  2675.  
  2676.     color(P_ORANGE);
  2677.     if (!dogfight)
  2678.     {
  2679.     bgnclosedline();
  2680.     v2f(plane[0]);
  2681.     v2f(plane[1]);
  2682.     v2f(plane[2]);
  2683.     v2f(plane[3]);
  2684.     v2f(plane[4]);
  2685.     v2f(plane[5]);
  2686.     v2f(plane[6]);
  2687.     v2f(plane[7]);
  2688.     v2f(plane[8]);
  2689.     v2f(plane[9]);
  2690.     v2f(plane[10]);
  2691.     v2f(plane[11]);
  2692.     v2f(plane[12]);
  2693.     endclosedline();
  2694.     }
  2695.     else
  2696.     rectf(-0.1, -0.1, 0.1, 0.1);
  2697.  
  2698.     popmatrix();
  2699.  
  2700.     drawmode(NORMALDRAW);
  2701.  
  2702.     frontbuffer(TRUE);
  2703.  
  2704.     COLOR(C_BLACK);
  2705.     clear_inst1();
  2706.  
  2707.     draw_plate(inst->plateobject, 0x3);
  2708.  
  2709.     frontbuffer(FALSE);
  2710.     popmatrix();
  2711. }
  2712.  
  2713.  
  2714. update_radar(radar_t *inst, int forceupdate)
  2715. {
  2716.     static float verts[4][2] = {{-9.0, -9.0}, {-9.0,  9.0},
  2717.                 { 9.0,  9.0}, { 9.0, -9.0}};
  2718.     static float n[][2] = {{-0.7,  6.0},    /* N */
  2719.                {-0.7,  8.0},
  2720.                { 0.7,  6.0},
  2721.                { 0.7,  8.0}};
  2722.     static float e[][2] = {{ 6.0, -0.7},    /* E */
  2723.                { 6.0,  0.7},
  2724.                { 8.0,  0.7},
  2725.                { 8.0, -0.7},
  2726.                { 7.0,  0.7},
  2727.                { 7.0, -0.3}};
  2728.     static float w[][2] = {{-8.0, -0.9},    /* W */
  2729.                {-6.0, -0.4},
  2730.                {-7.0,  0.0},
  2731.                {-6.0,  0.4},
  2732.                {-8.0,  0.9}};
  2733.     static float s[][2] = {{-0.7, -7.8},    /* S */
  2734.                {-0.5, -8.0},
  2735.                { 0.7, -8.0},
  2736.                { 0.7, -7.0},
  2737.                {-0.7, -7.0},
  2738.                {-0.7, -6.0},
  2739.                { 0.5, -6.0},
  2740.                { 0.7, -6.2}};
  2741.     int i;
  2742.  
  2743.     pushmatrix();
  2744.     translate(inst->px, inst->py, inst->pz);
  2745.     scale(inst->size, inst->size, inst->size);
  2746.  
  2747.     lsetdepth(zmaxscreen, zmaxscreen);
  2748.     scrmask(inst->sm_l, inst->sm_r, inst->sm_b, inst->sm_t);
  2749.     if (!in_cmode)
  2750.     zbuffer(TRUE);
  2751.  
  2752.     COLOR(C_BLACK);
  2753.     clear_inst1();
  2754.  
  2755.     rotate(-azimuth, 'z');
  2756.  
  2757.     scale(0.9, 0.9, 0.9);
  2758.  
  2759.     COLOR(C_WHITE);
  2760.     for (i=0; i < 72; i += 2)
  2761.     {
  2762.     bgnline(); v2f(inst->ticks[i]); v2f(inst->ticks[i+1]); endline();
  2763.     }
  2764.  
  2765.     bgnline();
  2766.     v2f(n[0]);
  2767.     v2f(n[1]);
  2768.     v2f(n[2]);
  2769.     v2f(n[3]);
  2770.     endline();
  2771.  
  2772.     bgnline();
  2773.     v2f(e[0]);
  2774.     v2f(e[1]);
  2775.     v2f(e[2]);
  2776.     v2f(e[3]);
  2777.     endline();
  2778.     bgnline();
  2779.     v2f(e[4]);
  2780.     v2f(e[5]);
  2781.     endline();
  2782.  
  2783.     bgnline();
  2784.     v2f(w[0]);
  2785.     v2f(w[1]);
  2786.     v2f(w[2]);
  2787.     v2f(w[3]);
  2788.     v2f(w[4]);
  2789.     endline();
  2790.  
  2791.     bgnline();
  2792.     v2f(s[0]);
  2793.     v2f(s[1]);
  2794.     v2f(s[2]);
  2795.     v2f(s[3]);
  2796.     v2f(s[4]);
  2797.     v2f(s[5]);
  2798.     v2f(s[6]);
  2799.     v2f(s[7]);
  2800.     endline();
  2801.  
  2802.     scale(0.0004, -0.0004, 0.0004);   /* scale down (y=-z)    */
  2803.     draw_radar_objects();
  2804.  
  2805.     if (!in_cmode)
  2806.     zbuffer(FALSE);
  2807.     else
  2808.     if (plate_ci_mode == NORMALDRAW)
  2809.         drawobj(inst->plateobject, 0x3);
  2810.     scrmask(0, xmaxwindow, 0, ymaxwindow);
  2811.     lsetdepth(zminscreen, zmaxscreen);
  2812.  
  2813.     popmatrix();
  2814. }
  2815.  
  2816.  
  2817.  
  2818. void init_radar(float px, float py, float pz, float size)
  2819. {
  2820.     radar_t *inst;
  2821.     int i, j;
  2822.     float r, sin, cos;
  2823.  
  2824.     inst = (radar_t *)malloc(sizeof(*inst));
  2825.     bzero(inst, sizeof(*inst));
  2826.     inst->px = px;
  2827.     inst->py = py;
  2828.     inst->pz = pz;
  2829.     inst->size = size;
  2830.     inst->plateobject = plate1;
  2831.  
  2832.     for (i=0, j=0; i < 3600; i += 100, j += 2)
  2833.     {
  2834.     gl_sincos(i, &sin, &cos);
  2835.     if (!(i%300) && (i%900))
  2836.         r = 7.5;       /* long line    */
  2837.     else
  2838.         r = 9.0;       /* short line   */
  2839.     inst->ticks[j][0] = 10.0 * sin;
  2840.     inst->ticks[j][1] = 10.0 * cos;
  2841.     inst->ticks[j+1][0] = r * sin;
  2842.     inst->ticks[j+1][1] = r * cos;
  2843.     }
  2844.  
  2845.     append_inst_list(draw_radar, update_radar, inst);
  2846. }
  2847.  
  2848.  
  2849. /************************************************************************
  2850. ***            Gyro compass functions                  ***
  2851. ************************************************************************/
  2852.  
  2853.  
  2854. typedef struct {
  2855.     float px, py, pz;        /* Position of instrument */
  2856.     float size;            /* Size of instrument */
  2857.     float last_head[2];        /* Previous heading of both buffers */
  2858.     float last_rot[2];
  2859.     object_t *plateobject;
  2860.     float ticks[36][6];
  2861.     float letters[27][3];
  2862. } compass_t;
  2863.  
  2864.  
  2865.  
  2866. /*
  2867.  * Draw the gyro compass
  2868.  */
  2869. draw_compass(compass_t *inst)
  2870. {
  2871.     static float verts[4][3] = { -9.0,-9.0,0.0, -9.0,9.0,0.0, 9.0,9.0,0.0,
  2872.             9.0,-9.0,0.0 };
  2873.     static float plane[13][3] =  { 0.0,0.0,0.6, .2,-1.0,0.6, 1.2,-1.8,0.6,
  2874.             1.2,-2.0,0.6, .2,-1.4,0.6, .2,-2.0,0.6, .5,-2.3, 0.6,
  2875.             -.5,-2.3,0.6, -.2,-2.0,0.6, -.2,-1.4,0.6, -1.2,-2.0,0.6,
  2876.             -1.2,-1.8,0.6, -.2,-1.0,0.6 };
  2877.     static float headmarks[8][3] = { -.2,-8.4,0.6, .2,-8.4,0.6, .2,-7.3,0.6,
  2878.             -.2,-7.3,0.6, -.2,8.4,0.6, .2,8.4,0.6, .2,7.3,0.6,
  2879.             -.2,7.3,0.6 };
  2880.     pushmatrix();
  2881.     translate(inst->px, inst->py, inst->pz);
  2882.     scale(inst->size, inst->size, inst->size);
  2883.     drawmode(UNDERDRAW);
  2884.     color(U_INST);
  2885.     clear_inst1();
  2886.  
  2887.     drawmode(PUPDRAW);
  2888.     color(P_MARKINGS);
  2889.     bgnclosedline();
  2890.     v3f(plane[0]);
  2891.     v3f(plane[1]);
  2892.     v3f(plane[2]);
  2893.     v3f(plane[3]);
  2894.     v3f(plane[4]);
  2895.     v3f(plane[5]);
  2896.     v3f(plane[6]);
  2897.     v3f(plane[7]);
  2898.     v3f(plane[8]);
  2899.     v3f(plane[9]);
  2900.     v3f(plane[10]);
  2901.     v3f(plane[11]);
  2902.     v3f(plane[12]);
  2903.     endclosedline();
  2904.  
  2905.     bgnpolygon();
  2906.     v3f(headmarks[0]);
  2907.     v3f(headmarks[1]);
  2908.     v3f(headmarks[2]);
  2909.     v3f(headmarks[3]);
  2910.     endpolygon();
  2911.     bgnpolygon();
  2912.     v3f(headmarks[4]);
  2913.     v3f(headmarks[5]);
  2914.     v3f(headmarks[6]);
  2915.     v3f(headmarks[7]);
  2916.     endpolygon();
  2917.  
  2918.     drawmode(NORMALDRAW);
  2919.     frontbuffer(TRUE);
  2920.  
  2921.     COLOR(C_BLACK);
  2922.     clear_inst1();
  2923.  
  2924.     draw_plate(inst->plateobject, 0x3);
  2925.  
  2926.     frontbuffer(FALSE);
  2927.     popmatrix();
  2928. }
  2929.  
  2930.  
  2931. update_compass(compass_t *inst, int forceupdate)
  2932. {
  2933.     static float verts[4][3] = { -9.0,-9.0,0.0, -9.0,9.0,0.0, 9.0,9.0,0.0,
  2934.             9.0,-9.0,0.0 };
  2935.     int current;
  2936.     int x;
  2937.     current = instrument_data.current;
  2938.     pushmatrix();
  2939.     translate(inst->px, inst->py, inst->pz);
  2940.     scale(inst->size, inst->size, inst->size);
  2941.     COLOR(C_BLACK);
  2942.     if (!in_cmode)
  2943.     {
  2944.     zbuffer(TRUE);
  2945.     clear_inst1();
  2946.     zbuffer(FALSE);
  2947.     }
  2948.     else
  2949.     clear_inst1();
  2950.     rot((float)azimuth, 'z');
  2951.     ICOLOR(instrument_data.text);
  2952.     for (x=0; x < 36; x++)
  2953.     {
  2954.     bgnline();
  2955.     v3f(inst->ticks[x]);
  2956.     v3f(inst->ticks[x]+3);
  2957.     endline();
  2958.     }
  2959.     bgnline();
  2960.     v3f(inst->letters[0]);
  2961.     v3f(inst->letters[1]);
  2962.     v3f(inst->letters[2]);
  2963.     v3f(inst->letters[3]);
  2964.     endline();
  2965.     bgnline();
  2966.     v3f(inst->letters[4]);
  2967.     v3f(inst->letters[5]);
  2968.     v3f(inst->letters[6]);
  2969.     v3f(inst->letters[7]);
  2970.     v3f(inst->letters[8]);
  2971.     endline();
  2972.     bgnline();
  2973.     v3f(inst->letters[9]);
  2974.     v3f(inst->letters[10]);
  2975.     v3f(inst->letters[11]);
  2976.     v3f(inst->letters[12]);
  2977.     endline();
  2978.     bgnline();
  2979.     v3f(inst->letters[13]);
  2980.     v3f(inst->letters[14]);
  2981.     endline();
  2982.     bgnline();
  2983.     v3f(inst->letters[15]);
  2984.     v3f(inst->letters[16]);
  2985.     v3f(inst->letters[17]);
  2986.     v3f(inst->letters[18]);
  2987.     v3f(inst->letters[19]);
  2988.     v3f(inst->letters[20]);
  2989.     v3f(inst->letters[21]);
  2990.     v3f(inst->letters[22]);
  2991.     v3f(inst->letters[23]);
  2992.     v3f(inst->letters[24]);
  2993.     v3f(inst->letters[25]);
  2994.     v3f(inst->letters[26]);
  2995.     endline();
  2996.     if (!in_cmode) ;
  2997.     popmatrix();
  2998. }
  2999.  
  3000.  
  3001.  
  3002. void init_compass(float px, float py, float pz, float size)
  3003. {
  3004.     compass_t *inst;
  3005.     int theta;
  3006.     float s,c;
  3007.     float outer_rad = 8.3;
  3008.     float big_inner_rad = 7.3;
  3009.     float small_inner_rad = 7.8;
  3010.     int i;
  3011.  
  3012.     inst = (compass_t *)malloc(sizeof(*inst));
  3013.     bzero(inst, sizeof(*inst));
  3014.     inst->px = px;
  3015.     inst->py = py;
  3016.     inst->pz = pz;
  3017.     inst->size = size;
  3018.     inst->plateobject = plate1;
  3019.  
  3020.     for (theta=i=0; theta < 360; theta += 10)
  3021.     {
  3022.     gl_sincos(theta*10, &s, &c);
  3023.     inst->ticks[i][0] = c * outer_rad;
  3024.     inst->ticks[i][1] = s * outer_rad;
  3025.     inst->ticks[i][2] = 0.0;
  3026.     if (theta % 30)
  3027.     {
  3028.         inst->ticks[i][3] = c * small_inner_rad;
  3029.         inst->ticks[i][4] = s * small_inner_rad;
  3030.         inst->ticks[i][5] = 0.0;
  3031.     }
  3032.     else
  3033.     {
  3034.         inst->ticks[i][3] = c * big_inner_rad;
  3035.         inst->ticks[i][4] = s * big_inner_rad;
  3036.         inst->ticks[i][5] = 0.0;
  3037.     }
  3038.     i++;
  3039.     }
  3040.     inst->letters[0][0]  = -0.5;
  3041.     inst->letters[0][1]  =  5.0;
  3042.     inst->letters[1][0]  = -0.5;
  3043.     inst->letters[1][1]  =  7.0;
  3044.     inst->letters[2][0]  =  0.5;
  3045.     inst->letters[2][1]  =  5.0;
  3046.     inst->letters[3][0]  =  0.5;
  3047.     inst->letters[3][1]  =  7.0;
  3048.     inst->letters[4][0]  = -7.0;
  3049.     inst->letters[4][1]  = -0.6;
  3050.     inst->letters[5][0]  = -5.0;
  3051.     inst->letters[5][1]  = -0.3;
  3052.     inst->letters[6][0]  = -6.0;
  3053.     inst->letters[6][1]  =  0.0;
  3054.     inst->letters[7][0]  = -5.0;
  3055.     inst->letters[7][1]  =  0.3;
  3056.     inst->letters[8][0]  = -7.0;
  3057.     inst->letters[8][1]  =  0.6;
  3058.     inst->letters[9][0]  =  7.0;
  3059.     inst->letters[9][1]  = -0.5;
  3060.     inst->letters[10][0] =  7.0;
  3061.     inst->letters[10][1] =  0.5;
  3062.     inst->letters[11][0] =  5.0;
  3063.     inst->letters[11][1] =  0.5;
  3064.     inst->letters[12][0] =  5.0;
  3065.     inst->letters[12][1] = -0.5;
  3066.     inst->letters[13][0] =  6.0;
  3067.     inst->letters[13][1] = -0.2;
  3068.     inst->letters[14][0] =  6.0;
  3069.     inst->letters[14][1] =  0.5;
  3070.     inst->letters[15][0] =  0.5;
  3071.     inst->letters[15][1] = -5.2;
  3072.     inst->letters[16][0] =  0.3;
  3073.     inst->letters[16][1] = -5.0;
  3074.     inst->letters[17][0] = -0.3;
  3075.     inst->letters[17][1] = -5.0;
  3076.     inst->letters[18][0] = -0.5;
  3077.     inst->letters[18][1] = -5.2;
  3078.     inst->letters[19][0] = -0.5;
  3079.     inst->letters[19][1] = -5.8;
  3080.     inst->letters[20][0] = -0.3;
  3081.     inst->letters[20][1] = -6.0;
  3082.     inst->letters[21][0] =  0.3;
  3083.     inst->letters[21][1] = -6.0;
  3084.     inst->letters[22][0] =  0.5;
  3085.     inst->letters[22][1] = -6.2;
  3086.     inst->letters[23][0] =  0.5;
  3087.     inst->letters[23][1] = -6.8;
  3088.     inst->letters[24][0] =  0.3;
  3089.     inst->letters[24][1] = -7.0;
  3090.     inst->letters[25][0] = -0.3;
  3091.     inst->letters[25][1] = -7.0;
  3092.     inst->letters[26][0] = -0.5;
  3093.     inst->letters[26][1] = -6.8;
  3094.  
  3095.     for (i=0; i <=26; i++)
  3096.     inst->letters[i][2] = 0.0;
  3097.  
  3098.     append_inst_list(draw_compass, update_compass, inst);
  3099. }
  3100.  
  3101.  
  3102. /************************************************************************
  3103. ***            Thrust & Throttle functions              ***
  3104. ************************************************************************/
  3105.  
  3106.  
  3107. typedef struct {
  3108.     float px, py, pz;        /* Position of instrument */
  3109.     float size;            /* Size of instrument */
  3110.     int last_thrust[2];        /* Previous thrust of both buffers */
  3111.     int   last_sign[2];        /* Previous sign of thrust of both buffers */
  3112.     int last_throttle[2];    /* Previous throttle of both buffers */
  3113.     float last_thrustrot[2];
  3114.     float last_throttlerot[2];
  3115.     float tickstep;
  3116.     int numticks;
  3117.     object_t *plateobject;
  3118. } thrustthrottle_t;
  3119.  
  3120.  
  3121.  
  3122. /*
  3123.  * Draw the thrust & throttle instrument
  3124.  */
  3125. draw_thrustthrottle(thrustthrottle_t *inst)
  3126. {
  3127.     static float verts[4][3] = { -9.0,-9.0,0.0, -9.0,9.0,0.0, 9.0,9.0,0.0,
  3128.             9.0,-9.0,0.0 };
  3129.     static float ticks[2][3] = { 0.0,5.5,0.0, 0.0,4.5,0.0 };
  3130.     static float smallticks[2][3] = { 0.0,5.5,0.0, 0.0,5.0,0.0 };
  3131.     static float revbox[4][3] = {{-7.5, -0.4, 0.0}, {-4.5, -0.4, 0.0},
  3132.                  {-4.5, -2.4, 0.0}, {-7.5, -2.4, 0.0}};
  3133.     short sl, sr, sb, st;
  3134.     int shift;
  3135.     char buf[8];
  3136.     int x;
  3137.     int thstep, tickstep, thcount;
  3138.     float angstep, tickangstep;
  3139.  
  3140.     getviewport(&sl,&sr,&sb,&st);
  3141.     pushmatrix();
  3142.     translate(inst->px, inst->py, inst->pz);
  3143.     scale(inst->size, inst->size, inst->size);
  3144.     if (!in_cmode)
  3145.     {
  3146.     drawmode(UNDERDRAW);
  3147.     color(U_INST);
  3148.     clear_inst1();
  3149.     color(MARKINGS);
  3150.     }
  3151.     else
  3152.     {
  3153.     drawmode(PUPDRAW);
  3154.     color(U_BLACK);
  3155.     clear_inst1();
  3156.     color(P_MARKINGS);
  3157.     }
  3158.  
  3159.     for (x=0; x<2; x++)
  3160.     {
  3161.     pushmatrix();
  3162.     translate(0.0,-7.5,0.0);
  3163.     thstep = inst->tickstep;
  3164.     tickstep = thstep / inst->numticks;
  3165.     angstep = -110.0 * inst->tickstep / 100.0;
  3166.     tickangstep = angstep / (float) inst->numticks;
  3167.     pushmatrix();
  3168.     rot(55.0, 'z');
  3169.     for (thcount=0; thcount <= 100; thcount += tickstep)
  3170.     {
  3171.         if (thcount % thstep)
  3172.         {
  3173.         bgnline();
  3174.         v3f(smallticks[0]);
  3175.         v3f(smallticks[1]);
  3176.         endline();
  3177.         }
  3178.         else
  3179.         {
  3180.         bgnline();
  3181.         v3f(ticks[0]);
  3182.         v3f(ticks[1]);
  3183.         endline();
  3184.         }
  3185.         rot(tickangstep, 'z');
  3186.     }
  3187.     popmatrix();
  3188.     pushviewport();
  3189.     viewport(sl-instrument_data.twowide, sr-instrument_data.twowide,
  3190.         sb-instrument_data.chartall, st-instrument_data.chartall);
  3191.     pushmatrix();
  3192.     rot(55.0, 'z');
  3193.     for (thcount=0; thcount <= 100; thcount += thstep)
  3194.     {
  3195.         sprintf(buf,"%d",thcount);
  3196.         cmov(0.0, 6.5, 0.0);
  3197.         charstr(buf);
  3198.         rot(angstep, 'z');
  3199.     }
  3200.     popviewport();
  3201.     popmatrix();
  3202.     popmatrix();
  3203.     scale(1.0,-1.0,1.0);
  3204.     }
  3205.     pushviewport();
  3206.     sprintf(buf,"%%");
  3207.     shift = strwidth(buf)/2 - 1;
  3208.     viewport(sl-shift, sr-shift, sb-instrument_data.chartall,
  3209.                     st-instrument_data.chartall);
  3210.     cmov(0.0,-5.9,0.0);
  3211.     charstr(buf);
  3212.     cmov(0.0,4.7,0.0);
  3213.     charstr(buf);
  3214.     popviewport();
  3215.     pushviewport();
  3216.     viewport(sl-instrument_data.eightwide, sr-instrument_data.eightwide,
  3217.          sb-instrument_data.chartall, st-instrument_data.chartall);
  3218.     cmov(0.0,5.9,0.0);
  3219.     charstr("THROTTLE");
  3220.     popviewport();
  3221.     pushviewport();
  3222.     viewport(sl-instrument_data.sixwide, sr-instrument_data.sixwide,
  3223.          sb-instrument_data.chartall, st-instrument_data.chartall);
  3224.     cmov(0.0,-4.7,0.0);
  3225.     charstr("THRUST");
  3226.     popviewport();
  3227.  
  3228.     /*
  3229.      *  clear underlays form warning light area
  3230.      */
  3231.     color(U_BLACK);
  3232.     drawneedlebox(revbox);
  3233.  
  3234.     drawmode(NORMALDRAW);
  3235.     frontbuffer(TRUE);
  3236.  
  3237.     COLOR(C_BLACK);
  3238.     clear_inst1();
  3239.  
  3240.     draw_plate(inst->plateobject, 0x3);
  3241.  
  3242.     frontbuffer(FALSE);
  3243.     popmatrix();
  3244. }
  3245.  
  3246.  
  3247.  
  3248. update_thrustthrottle(thrustthrottle_t *inst, int forceupdate)
  3249. {
  3250.     static float throtneedle[5][3] = {{-0.2,  0.0, 0.0}, {-0.2, -3.1, 0.0},
  3251.                       { 0.0, -4.1, 0.0}, { 0.2, -3.1, 0.0},
  3252.                       { 0.2,  0.0, 0.0}};
  3253.     static float throtneedlebox[4][3] = {{-0.6, 0.35, 0.0}, {-0.6,-4.5,  0.0},
  3254.                       {0.6,-4.5,  0.0}, { 0.6, 0.35, 0.0}};
  3255.     static float thrustneedle[5][3] = {{-0.2, 0.0, 0.0}, {-0.2, 3.1, 0.0},
  3256.                        { 0.0, 4.1, 0.0}, { 0.2, 3.1, 0.0},
  3257.                        { 0.2, 0.0, 0.0}};
  3258.     static float thrustneedlebox[4][3] = {{-0.6,-0.35, 0.0}, {-0.6, 4.5, 0.0},
  3259.                       { 0.6, 4.5,  0.0}, { 0.6,-0.35,0.0}};
  3260.     static float revbox[4][3] = {{-7.5, -0.4, 0.0}, {-4.5, -0.4, 0.0},
  3261.                  {-4.5, -2.4, 0.0}, {-7.5, -2.4, 0.0}};
  3262.     int current;
  3263.     int sign = 1;
  3264.  
  3265.     current = instrument_data.current;
  3266.  
  3267.     pushmatrix();
  3268.     translate(inst->px, inst->py, inst->pz);
  3269.     scale(inst->size, inst->size, inst->size);
  3270.  
  3271.     if ((thrust != inst->last_thrust[current]) || forceupdate)
  3272.     {
  3273.     pushmatrix();
  3274.     translate(0.0,-7.5,0.0);
  3275.     COLOR(C_BLACK);
  3276.     pushmatrix();
  3277.     rot(inst->last_thrustrot[current], 'z');
  3278.     drawneedlebox(thrustneedlebox);
  3279.     popmatrix();
  3280. #ifndef NO_MS
  3281.     if (ms_samples)
  3282.     {
  3283.         pushmatrix();
  3284.         rot(inst->last_thrustrot[!current], 'z');
  3285.         drawneedlebox(thrustneedlebox);
  3286.         popmatrix();
  3287.     }
  3288. #endif
  3289.  
  3290.     if (_ABS(thrust) > 100)
  3291.         inst->last_thrustrot[current] = -55.0;
  3292.     else
  3293.         inst->last_thrustrot[current] =
  3294.                     55.0 - fabs((110.0 * thrust) / 100.0);
  3295.     drawneedle(inst->last_thrustrot[current],
  3296.            instrument_data.darkneedle, thrustneedle);
  3297.     popmatrix();
  3298.     inst->last_thrust[current] = thrust;
  3299.     }
  3300.  
  3301.     if ((throttle != inst->last_throttle[current]) || forceupdate)
  3302.     {
  3303.     if (throttle < 0) sign = -1;
  3304.     if (sign != inst->last_sign[current])
  3305.     {
  3306.         inst->last_sign[current] = sign;
  3307.         if (sign == 1)
  3308.         {
  3309.         COLOR(C_DRED);
  3310.         drawneedlebox(revbox);
  3311.         ICOLOR(instrument_data.textborder);
  3312.         bgnclosedline();
  3313.         v3f(revbox[0]);
  3314.         v3f(revbox[1]);
  3315.         v3f(revbox[2]);
  3316.         v3f(revbox[3]);
  3317.         endclosedline();
  3318.         ICOLOR(instrument_data.backlittext);
  3319.         cmov(-7.2,-1.8,0.0);
  3320.         charstr("REV");
  3321.         }
  3322.         else
  3323.         {
  3324.         COLOR(C_RED);
  3325.         drawneedlebox(revbox);
  3326.         ICOLOR(instrument_data.textborder);
  3327.         bgnclosedline();
  3328.         v3f(revbox[0]);
  3329.         v3f(revbox[1]);
  3330.         v3f(revbox[2]);
  3331.         v3f(revbox[3]);
  3332.         endclosedline();
  3333.         ICOLOR(instrument_data.backlittext);
  3334.         cmov(-7.2,-1.8,0.0);
  3335.         charstr("REV");
  3336.         }
  3337.     }
  3338.  
  3339.     pushmatrix();
  3340.     translate(0.0,7.5,0.0);
  3341.     COLOR(C_BLACK);
  3342.     pushmatrix();
  3343.     rot(inst->last_throttlerot[current], 'z');
  3344.     drawneedlebox(throtneedlebox);
  3345.     popmatrix();
  3346. #ifndef NO_MS
  3347.     if (ms_samples)
  3348.     {
  3349.         pushmatrix();
  3350.         rot(inst->last_throttlerot[!current], 'z');
  3351.         drawneedlebox(throtneedlebox);
  3352.         popmatrix();
  3353.     }
  3354. #endif
  3355.  
  3356.     if (_ABS(throttle) > 100)
  3357.         inst->last_throttlerot[current] = 55.0;
  3358.     else
  3359.         inst->last_throttlerot[current] = fabs((110.0 * throttle) /
  3360.                            -100.0) - 55.0;
  3361.     drawneedle(inst->last_throttlerot[current],
  3362.            instrument_data.darkneedle, throtneedle);
  3363.     popmatrix();
  3364.     inst->last_throttle[current] = throttle;
  3365.     }
  3366.     popmatrix();
  3367. }
  3368.  
  3369.  
  3370.  
  3371. void init_thrustthrottle(float px, float py, float pz, float size,
  3372.              float tickstep, int numticks)
  3373. {
  3374.     thrustthrottle_t *inst;
  3375.  
  3376.     inst = (thrustthrottle_t *)malloc(sizeof(*inst));
  3377.     bzero(inst, sizeof(*inst));
  3378.     inst->px = px;
  3379.     inst->py = py;
  3380.     inst->pz = pz;
  3381.     inst->size = size;
  3382.     inst->plateobject = plate1;
  3383.     inst->numticks = numticks;
  3384.     inst->tickstep = tickstep;
  3385.     inst->last_thrust[0]= inst->last_thrust[1]= thrust + 1.0;
  3386.     inst->last_throttle[0]= inst->last_throttle[1]=
  3387.                 throttle + 1.0;
  3388.     append_inst_list(draw_thrustthrottle, update_thrustthrottle, inst);
  3389. }
  3390.  
  3391.  
  3392.  
  3393. /************************************************************************
  3394. ***                Fuel functions                  ***
  3395. ************************************************************************/
  3396.  
  3397.  
  3398. typedef struct {
  3399.     float px, py, pz;        /* Position of instrument */
  3400.     float size;            /* Size of instrument */
  3401.     object_t *plateobject;
  3402.     float last_fuel[2];        /* Previous fuel of both buffers */
  3403.     float last_fuelrot[2];
  3404.     float maxfuel;
  3405.     float tickstep;
  3406.     int numticks;
  3407.     int scale;
  3408. } fuelgauge_t;
  3409.  
  3410.  
  3411.  
  3412. /*
  3413.  * Draw the fuel & consumption instrument
  3414.  */
  3415. draw_fuelgauge(fuelgauge_t *inst)
  3416. {
  3417.     static float verts[4][3] = {{-9.0, -9.0, 0.0}, {-9.0,  9.0, 0.0},
  3418.                 { 9.0,  9.0, 0.0}, { 9.0, -9.0, 0.0}};
  3419.     static float ticks[2][3] = {{0.0, 5.5, 0.0}, {0.0, 4.5, 0.0}};
  3420.     static float smallticks[2][3] = {{0.0, 5.5, 0.0}, {0.0, 5.0, 0.0}};
  3421.     short sl, sr, sb, st;
  3422.     int shift;
  3423.     char buf[8];
  3424.     int x;
  3425.     int mfuel, flstep, tickstep, flcount;
  3426.     float angstep, tickangstep;
  3427.  
  3428.     getviewport(&sl,&sr,&sb,&st);
  3429.     pushmatrix();
  3430.     translate(inst->px, inst->py, inst->pz);
  3431.     scale(inst->size, inst->size, inst->size);
  3432.  
  3433.     if (!in_cmode)
  3434.     {
  3435.     drawmode(UNDERDRAW);
  3436.  
  3437.     color(U_INST);
  3438.     clear_inst1();
  3439.     color(MARKINGS);
  3440.     }
  3441.     else
  3442.     {
  3443.     drawmode(PUPDRAW);
  3444.  
  3445.     color(U_BLACK);
  3446.     clear_inst1();
  3447.     color(P_MARKINGS);
  3448.     }
  3449.  
  3450.     mfuel = inst->maxfuel;/* / inst->scale;*/
  3451.     flstep = inst->tickstep;/* / inst->scale;*/
  3452.     tickstep = flstep / inst->numticks;
  3453.     angstep = -180.0 * inst->tickstep / inst->maxfuel;
  3454.     tickangstep = angstep / (float) inst->numticks;
  3455.     pushmatrix();
  3456.     rot(90.0, 'z');
  3457.     for (flcount=0; flcount <= mfuel; flcount += tickstep)
  3458.     {
  3459.     if (flcount % flstep)
  3460.     {
  3461.         bgnline();
  3462.         v3f(smallticks[0]);
  3463.         v3f(smallticks[1]);
  3464.         endline();
  3465.     }
  3466.     else
  3467.     {
  3468.         bgnline();
  3469.         v3f(ticks[0]);
  3470.         v3f(ticks[1]);
  3471.         endline();
  3472.     }
  3473.     rot(tickangstep, 'z');
  3474.     }
  3475.     popmatrix();
  3476.  
  3477.     pushviewport();
  3478.  
  3479.     sprintf(buf, "%d", (mfuel >> 1) / inst->scale);
  3480.     shift = (strwidth(buf) >> 1) - 1;
  3481.     viewport(sl-shift, sr-shift,
  3482.          sb-instrument_data.chartall, st-instrument_data.chartall);
  3483.     pushmatrix();
  3484.     rot(90.0, 'z');
  3485.     for (flcount=0; flcount <= mfuel; flcount += flstep)
  3486.     {
  3487.     sprintf(buf, "%d", flcount / inst->scale);
  3488.     cmov(0.0, 6.5, 0.0);
  3489.     charstr(buf);
  3490.     rot(angstep, 'z');
  3491.     }
  3492.     popviewport();
  3493.     popmatrix();
  3494.  
  3495.     pushviewport();
  3496.     sprintf(buf,"x%d", inst->scale);
  3497.     shift = (strwidth(buf) >> 1) - 1;
  3498.     viewport(sl-shift, sr-shift,
  3499.          sb-instrument_data.chartall, st-instrument_data.chartall);
  3500.     cmov(0.0,-5.9,0.0);
  3501.     charstr(buf);
  3502.     popviewport();
  3503.  
  3504.     pushviewport();
  3505.     shift = (strwidth("FUEL LBS") >> 1) - 1;
  3506.     viewport(sl-shift, sr-shift,
  3507.          sb-instrument_data.chartall, st-instrument_data.chartall);
  3508.     cmov(0.0,-4.0,0.0);
  3509.     charstr("FUEL LBS");
  3510.     popviewport();
  3511.  
  3512.     drawmode(NORMALDRAW);
  3513.     frontbuffer(TRUE);
  3514.  
  3515.     COLOR(C_BLACK);
  3516.     clear_inst1();
  3517.  
  3518.     draw_plate(inst->plateobject, 0x3);
  3519.  
  3520.     frontbuffer(FALSE);
  3521.     popmatrix();
  3522. }
  3523.  
  3524.  
  3525. update_fuelgauge(fuelgauge_t *inst, int forceupdate)
  3526. {
  3527.     static float needle[5][3]    = { -.2,0.0,0.0, -.2,3.1,0.0, 0.0,4.1,0.0,
  3528.                 .2,3.1,0.0, .2,0.0,0.0 };
  3529.     static float needlebox[4][3] = { -.6,-0.35,0.0, -.6,4.5,0.0, .6,4.5,0.0,
  3530.                 .6,-0.35,0.0 };
  3531.     static float low_light[4][2] = {{-1.5, -1.0}, {-1.5, -3.0},
  3532.                     { 1.5, -3.0}, { 1.5, -1.0}};
  3533.     int current;
  3534.  
  3535.     current = instrument_data.current;
  3536.  
  3537.     pushmatrix();
  3538.     translate(inst->px, inst->py, inst->pz);
  3539.     scale(inst->size, inst->size, inst->size);
  3540.  
  3541.     if ((fuel != inst->last_fuel[current]) || forceupdate)
  3542.     {
  3543.     COLOR(C_BLACK);
  3544.     pushmatrix();
  3545.     rot(inst->last_fuelrot[current], 'z');
  3546.     drawneedlebox(needlebox);
  3547.     popmatrix();
  3548. #ifndef NO_MS
  3549.     if (ms_samples)
  3550.     {
  3551.         pushmatrix();
  3552.         rot(inst->last_fuelrot[!current], 'z');
  3553.         drawneedlebox(needlebox);
  3554.         popmatrix();
  3555.     }
  3556. #endif
  3557.  
  3558.     if (fuel < 00)
  3559.         inst->last_fuelrot[current] = 90.0;
  3560.     else
  3561.         inst->last_fuelrot[current] = -180.0 * fuel / (100 << 7) + 90.0;
  3562.     drawneedle(inst->last_fuelrot[current], instrument_data.darkneedle,
  3563.            needle);
  3564.  
  3565.     if (fuel < (10<<7))    /* 10% or less fuel left */
  3566.         COLOR(C_RED);
  3567.     else
  3568.         COLOR(C_DRED);
  3569.     bgnpolygon();
  3570.     v2f(low_light[0]); v2f(low_light[1]);
  3571.     v2f(low_light[2]); v2f(low_light[3]);
  3572.     endpolygon();
  3573.     ICOLOR(instrument_data.textborder);
  3574.     bgnclosedline();
  3575.     v2f(low_light[0]); v2f(low_light[1]);
  3576.     v2f(low_light[2]); v2f(low_light[3]);
  3577.     endclosedline();
  3578.  
  3579.     }
  3580.  
  3581.     popmatrix();
  3582. }
  3583.  
  3584.  
  3585. static fuelgauge_t *fg;
  3586.  
  3587. void init_fuelgauge(float px, float py, float pz, float size,
  3588.             float maxfuel, float tickstep, int numticks, int scale)
  3589. {
  3590.     fuelgauge_t *inst;
  3591.  
  3592.     inst = (fuelgauge_t *)malloc(sizeof(*inst));
  3593.     bzero(inst, sizeof(*inst));
  3594.     inst->px = px;
  3595.     inst->py = py;
  3596.     inst->pz = pz;
  3597.     inst->size = size;
  3598.     inst->plateobject = plate1;
  3599.     inst->maxfuel = maxfuel;
  3600.     inst->numticks = numticks;
  3601.     inst->tickstep = tickstep;
  3602.     inst->scale = scale;
  3603.     inst->last_fuel[0]= inst->last_fuel[1]= fuel + 1.0;
  3604.     fg = inst;
  3605.  
  3606.     append_inst_list(draw_fuelgauge, update_fuelgauge, inst);
  3607. }
  3608.  
  3609.  
  3610. void set_fuelgauge(float maxfuel, float tickstep, int numticks, int scale)
  3611. {
  3612.     fg->maxfuel = maxfuel;
  3613.     fg->tickstep = tickstep;
  3614.     fg->numticks = numticks;
  3615.     fg->scale = scale;
  3616. }
  3617.  
  3618.  
  3619.  
  3620. /************************************************************************
  3621. ***            Flaps & Spoilers functions              ***
  3622. ************************************************************************/
  3623.  
  3624.  
  3625. typedef struct {
  3626.     float px, py, pz;        /* Position of instrument */
  3627.     float size;            /* Size of instrument */
  3628.     object_t *plateobject;
  3629.     float last_flap[2];        /* Previous flap of both buffers */
  3630.     float last_spoiler[2];    /* Previous spoiler of both buffers */
  3631.     float last_flaprot[2];
  3632.     float last_spoilerrot[2];
  3633.     int maxflap;
  3634.     int flaptickstep;
  3635.     int numflapticks;
  3636.     int maxspoiler;
  3637.     int spoilertickstep;
  3638.     int numspoilerticks;
  3639. } flapspoiler_t;
  3640.  
  3641.  
  3642.  
  3643. /*
  3644.  * Draw the flaps & spoilers instrument
  3645.  */
  3646. draw_flapspoiler(flapspoiler_t *inst)
  3647. {
  3648.     static float verts[4][3] = { -9.0,-9.0,0.0, -9.0,9.0,0.0, 9.0,9.0,0.0,
  3649.             9.0,-9.0,0.0 };
  3650.     static float ticks[2][3] = { 0.0,5.3,0.0, 0.0,4.3,0.0 };
  3651.     static float smallticks[2][3] = { 0.0,5.3,0.0, 0.0,4.7,0.0 };
  3652.     short sl, sr, sb, st;
  3653.     int shift;
  3654.     char buf[8];
  3655.     int x;
  3656.     int flcount, smalltickstep;
  3657.     float angstep, tickangstep;
  3658.     getviewport(&sl,&sr,&sb,&st);
  3659.  
  3660.     pushmatrix();
  3661.     translate(inst->px, inst->py, inst->pz);
  3662.     scale(inst->size, inst->size, inst->size);
  3663.  
  3664.     if (!in_cmode)
  3665.     {
  3666.     drawmode(UNDERDRAW);
  3667.  
  3668.     color(U_INST);
  3669.     clear_inst1();
  3670.  
  3671.     color(MARKINGS);
  3672.     }
  3673.     else
  3674.     {
  3675.     drawmode(PUPDRAW);
  3676.  
  3677.     color(U_BLACK);
  3678.     clear_inst1();
  3679.  
  3680.     color(P_MARKINGS);
  3681.     }
  3682.  
  3683.     if (inst->maxflap)
  3684.     {
  3685.     pushviewport();
  3686.     viewport(sl-instrument_data.fourwide, sr-instrument_data.fourwide,
  3687.          sb-instrument_data.chartall, st-instrument_data.chartall);
  3688.     cmov(0.0,-5.5,0.0);
  3689.     charstr("FLAP");
  3690.     popviewport();
  3691.  
  3692.     pushmatrix();
  3693.     translate(0.0,-7.5,0.0);
  3694.     pushmatrix();
  3695.  
  3696.     smalltickstep = inst->flaptickstep / inst->numflapticks;
  3697.     angstep= -110.0 * (float)inst->flaptickstep /
  3698.          (float)inst->maxflap;
  3699.     tickangstep = angstep / (float) inst->numflapticks;
  3700.     rot(55.0, 'z');
  3701.     for (flcount=0; flcount <= inst->maxflap;
  3702.          flcount += smalltickstep)
  3703.     {
  3704.         if (flcount % inst->flaptickstep)
  3705.         {
  3706.         bgnline();
  3707.         v3f(smallticks[0]);
  3708.         v3f(smallticks[1]);
  3709.         endline();
  3710.         }
  3711.         else
  3712.         {
  3713.         bgnline();
  3714.         v3f(ticks[0]);
  3715.         v3f(ticks[1]);
  3716.         endline();
  3717.         }
  3718.         rot(tickangstep, 'z');
  3719.     }
  3720.     popmatrix();
  3721.  
  3722.     pushviewport();
  3723.     viewport(sl-instrument_data.twowide, sr-instrument_data.twowide,
  3724.          sb-instrument_data.chartall, st-instrument_data.chartall);
  3725.     translate(0.0,0.5,0.0);
  3726.     rot(55.0, 'z');
  3727.     for (flcount=0; flcount <= inst->maxflap;
  3728.          flcount += inst->flaptickstep)
  3729.     {
  3730.         sprintf(buf,"%d",flcount);
  3731.         if (flcount==0)
  3732.         {
  3733.         pushviewport();
  3734.         viewport(sl-instrument_data.charwide,
  3735.              sr-instrument_data.charwide,
  3736.              sb-instrument_data.chartall,
  3737.              st-instrument_data.chartall);
  3738.         }
  3739.         cmov(0.0, 7.0, 0.0);
  3740.         charstr(buf);
  3741.         rot(angstep, 'z');
  3742.         if (flcount==0)
  3743.         popviewport();
  3744.     }
  3745.     popviewport();
  3746.     popmatrix();
  3747.     }
  3748.  
  3749.     if (inst->maxspoiler)
  3750.     {
  3751.     pushviewport();
  3752.     viewport(sl-instrument_data.fivewide, sr-instrument_data.fivewide,
  3753.          sb-instrument_data.chartall, st-instrument_data.chartall);
  3754.     cmov(0.0,5.5,0.0);
  3755.     charstr("SPOIL");
  3756.     popviewport();
  3757.  
  3758.     pushmatrix();
  3759.     translate(0.0,7.5,0.0);
  3760.  
  3761.     smalltickstep = inst->spoilertickstep /
  3762.             inst->numspoilerticks;
  3763.     angstep= 110.0 * (float)inst->spoilertickstep /
  3764.          (float)inst->maxspoiler;
  3765.     tickangstep = angstep / (float) inst->numspoilerticks;
  3766.     pushmatrix();
  3767.     rot(125.0, 'z');
  3768.     for (flcount=0; flcount <= inst->maxspoiler;
  3769.          flcount += smalltickstep)
  3770.     {
  3771.         if (flcount % inst->spoilertickstep)
  3772.         {
  3773.         bgnline();
  3774.         v3f(smallticks[0]);
  3775.         v3f(smallticks[1]);
  3776.         endline();
  3777.         }
  3778.         else
  3779.         {
  3780.         bgnline();
  3781.         v3f(ticks[0]);
  3782.         v3f(ticks[1]);
  3783.         endline();
  3784.         }
  3785.         rot(tickangstep, 'z');
  3786.     }
  3787.     popmatrix();
  3788.     pushviewport();
  3789.     viewport(sl-instrument_data.twowide, sr-instrument_data.twowide,
  3790.          sb-instrument_data.chartall, st-instrument_data.chartall);
  3791.     translate(0.0,-0.5,0.0);
  3792.     rot(125.0, 'z');
  3793.     for (flcount=0; flcount <= inst->maxspoiler;
  3794.          flcount += inst->spoilertickstep)
  3795.     {
  3796.         if (flcount==0)
  3797.         {
  3798.         pushviewport();
  3799.         viewport(sl-instrument_data.charwide,
  3800.              sr-instrument_data.charwide,
  3801.              sb-instrument_data.chartall,
  3802.              st-instrument_data.chartall);
  3803.         }
  3804.         sprintf(buf,"%d",flcount);
  3805.         cmov(0.0, 7.0, 0.0);
  3806.         charstr(buf);
  3807.         rot(angstep, 'z');
  3808.         if (flcount==0)
  3809.         popviewport();
  3810.     }
  3811.     popviewport();
  3812.     popmatrix();
  3813.     }
  3814.  
  3815.     drawmode(NORMALDRAW);
  3816.     frontbuffer(TRUE);
  3817.  
  3818.     COLOR(C_BLACK);
  3819.     clear_inst1();
  3820.  
  3821.     draw_plate(inst->plateobject, 0x3);
  3822.  
  3823.     frontbuffer(FALSE);
  3824.     popmatrix();
  3825. }
  3826.  
  3827.  
  3828. update_flapspoiler(flapspoiler_t *inst, int forceupdate)
  3829. {
  3830.     static float flapneedle[5][3]    = { -.3,0.0,0.0, -.3,4.1,0.0, 0.0,5.1,0.0,
  3831.                     .3,4.1,0.0, .3,0.0,0.0 };
  3832.     static float flapneedlebox[4][3] = { -.6,-0.35,0.0, -.6,5.5,0.0, .6,5.5,0.0,
  3833.                     .6,-0.35,0.0 };
  3834.     static float spoilneedle[5][3]   = { -.3,0.0,0.0, -.3,-4.1,0.0,
  3835.                     0.0,-5.1,0.0, .3,-4.1,0.0, .3,0.0,0.0 };
  3836.     static float spoilneedlebox[4][3]= { -.6,0.35,0.0, -.6,-5.5,0.0,
  3837.                     .6,-5.5,0.0, .6,0.35,0.0 };
  3838.     int current;
  3839.  
  3840.     current = instrument_data.current;
  3841.  
  3842.     pushmatrix();
  3843.     translate(inst->px, inst->py, inst->pz);
  3844.     scale(inst->size, inst->size, inst->size);
  3845.  
  3846.     if ((flaps != inst->last_flap[current] || forceupdate) &&
  3847.     inst->maxflap)
  3848.     {
  3849.     pushmatrix();
  3850.     translate(0.0,-7.5,0.0);
  3851.     COLOR(C_BLACK);
  3852.     pushmatrix();
  3853.     rot(inst->last_flaprot[current], 'z');
  3854.     drawneedlebox(flapneedlebox);
  3855.     popmatrix();
  3856. #ifndef NO_MS
  3857.     if (ms_samples)
  3858.     {
  3859.         pushmatrix();
  3860.         rot(inst->last_flaprot[!current], 'z');
  3861.         drawneedlebox(flapneedlebox);
  3862.         popmatrix();
  3863.     }
  3864. #endif
  3865.  
  3866.     if (flaps > inst->maxflap)
  3867.         inst->last_flaprot[current] = -55.0;
  3868.     else if (flaps <= 0)
  3869.         inst->last_flaprot[current] =  55.0;
  3870.     else
  3871.         inst->last_flaprot[current] = -110.0 * (float)flaps
  3872.                     / (float)inst->maxflap + 55.0;
  3873.     drawneedle(inst->last_flaprot[current],
  3874.            instrument_data.darkneedle, flapneedle);
  3875.     popmatrix();
  3876.     inst->last_flap[current] = flaps;
  3877.     }
  3878.  
  3879.     if ((spoilers != inst->last_spoiler[current] || forceupdate) &&
  3880.     inst->maxspoiler)
  3881.     {
  3882.     pushmatrix();
  3883.     translate(0.0,7.5,0.0);
  3884.     COLOR(C_BLACK);
  3885.     pushmatrix();
  3886.     rot(inst->last_spoilerrot[current], 'z');
  3887.     drawneedlebox(spoilneedlebox);
  3888.     popmatrix();
  3889. #ifndef NO_MS
  3890.     if (ms_samples)
  3891.     {
  3892.         pushmatrix();
  3893.         rot(inst->last_spoilerrot[!current], 'z');
  3894.         drawneedlebox(spoilneedlebox);
  3895.         popmatrix();
  3896.     }
  3897. #endif
  3898.  
  3899.     if (spoilers > inst->maxspoiler)
  3900.         inst->last_spoilerrot[current] = 55.0;
  3901.     else if (spoilers < 0)
  3902.         inst->last_spoilerrot[current] = -55.0;
  3903.     else
  3904.         inst->last_spoilerrot[current] = 110.0 * spoilers
  3905.                     / (float)inst->maxspoiler - 55.0;
  3906.     drawneedle(inst->last_spoilerrot[current],
  3907.            instrument_data.darkneedle, spoilneedle);
  3908.     popmatrix();
  3909.     inst->last_spoiler[current] = spoilers;
  3910.     }
  3911.  
  3912.     popmatrix();
  3913. }
  3914.  
  3915.  
  3916. static flapspoiler_t *fs;
  3917.  
  3918. void init_flapspoiler(float px, float py, float pz, float size,
  3919.               int maxflap, int flaptickstep, int numflapticks,
  3920.               int maxspoiler, int spoilertickstep, int numspoilerticks)
  3921. {
  3922.     flapspoiler_t *inst;
  3923.  
  3924.     inst = (flapspoiler_t *)malloc(sizeof(*inst));
  3925.     bzero(inst, sizeof(*inst));
  3926.     inst->px = px;
  3927.     inst->py = py;
  3928.     inst->pz = pz;
  3929.     inst->size = size;
  3930.     inst->plateobject = plate1;
  3931.     inst->maxflap = maxflap;
  3932.     inst->flaptickstep = flaptickstep;
  3933.     inst->numflapticks = numflapticks;
  3934.     inst->maxspoiler = maxspoiler;
  3935.     inst->spoilertickstep = spoilertickstep;
  3936.     inst->numspoilerticks = numspoilerticks;
  3937.     inst->last_flap[0] = inst->last_flap[1] = flaps + 10.0;
  3938.     inst->last_spoiler[0] = inst->last_spoiler[1] = spoilers + 10.0;
  3939.     fs = inst;
  3940.  
  3941.     append_inst_list(draw_flapspoiler, update_flapspoiler, inst);
  3942. }
  3943.  
  3944.  
  3945. void set_flapspoiler(int maxflap, int flaptickstep, int numflapticks,
  3946.              int maxspoiler, int spoilertickstep, int numspoilerticks)
  3947. {
  3948.     fs->maxflap = maxflap;
  3949.     fs->flaptickstep = flaptickstep;
  3950.     fs->numflapticks = numflapticks;
  3951.     fs->maxspoiler = maxspoiler;
  3952.     fs->spoilertickstep = spoilertickstep;
  3953.     fs->numspoilerticks = numspoilerticks;
  3954. }
  3955.  
  3956.  
  3957. /************************************************************************
  3958. ***                Landinggear functions              ***
  3959. ************************************************************************/
  3960.  
  3961.  
  3962. typedef struct {
  3963.     float px, py, pz;        /* Position of instrument */
  3964.     float size;            /* Size of instrument */
  3965.     object_t *plateobject;
  3966.     int last_state[2];
  3967.     int framec;
  3968.     int sliding;
  3969.     float transfactor;
  3970.     int numframes;
  3971.     int forcedraw;
  3972.     int forcenodraw;
  3973. } gear_t;
  3974.  
  3975.  
  3976. /*
  3977.  * Draw the landing gear indicator
  3978.  */
  3979. draw_gear(gear_t *inst)
  3980. {
  3981.     short sl, sr, sb, st;
  3982.     static float verts[4][3] = { -9.0,-9.0,0.0, -9.0,9.0,0.0, 9.0,9.0,0.0,
  3983.             9.0,-9.0,0.0 };
  3984.  
  3985.     getviewport(&sl,&sr,&sb,&st);
  3986.  
  3987.     pushmatrix();
  3988.     translate(inst->px, inst->py, inst->pz);
  3989.     scale(inst->size, inst->size, inst->size);
  3990.  
  3991.     if (!in_cmode)
  3992.     {
  3993.     drawmode(UNDERDRAW);
  3994.  
  3995.     color(U_INST);
  3996.     clear_inst1();
  3997.  
  3998.     color(MARKINGS);
  3999.     }
  4000.     else
  4001.     {
  4002.     drawmode(PUPDRAW);
  4003.  
  4004.     color(U_BLACK);
  4005.     clear_inst1();
  4006.  
  4007.     color(P_MARKINGS);
  4008.     }
  4009.  
  4010.     pushviewport();
  4011.     viewport(sl-instrument_data.fourwide, sr-instrument_data.fourwide,
  4012.          sb-instrument_data.chartall, st-instrument_data.chartall);
  4013.     cmov(0.0,0.0,0.0);
  4014.     charstr("GEAR");
  4015.     popviewport();
  4016.  
  4017.     drawmode(NORMALDRAW);
  4018.  
  4019.     frontbuffer(TRUE);
  4020.  
  4021.     COLOR(C_BLACK);
  4022.     clear_inst1();
  4023.  
  4024.     draw_plate(inst->plateobject, 0x3);
  4025.  
  4026.     frontbuffer(FALSE);
  4027.     popmatrix();
  4028. }
  4029.  
  4030.  
  4031. update_gear_drawlamp()
  4032. {
  4033.     static float box[4][3]  = { -2.0,-1.25,0.0, -2.0,1.25,0.0, 2.0,1.25,0.0,
  4034.                 2.0,-1.25,0.0 };
  4035.     bgnpolygon();
  4036.     v3f(box[0]);
  4037.     v3f(box[1]);
  4038.     v3f(box[2]);
  4039.     v3f(box[3]);
  4040.     endpolygon();
  4041.     ICOLOR(instrument_data.textborder);
  4042.     bgnclosedline();
  4043.     v3f(box[0]);
  4044.     v3f(box[1]);
  4045.     v3f(box[2]);
  4046.     v3f(box[3]);
  4047.     endclosedline();
  4048. }
  4049.  
  4050.  
  4051. update_gear_drawstripes()
  4052. {
  4053.     static float stripes[16][3] = { -2.0,.25,0.0, -2.0,1.25,0.0, -1.0,1.25,0.0,
  4054.                 -2.0,-1.25,0.0, -2.0,-.5,0.0, -.25,1.25,0.0,
  4055.                 .5,1.25,0.0, -.5,-1.25,0.0, -1.25,-1.25,0.0,
  4056.                 1.25,1.25,0.0, 2.0,1.25,0.0, 1.0,-1.25,0.0,
  4057.                 .25,-1.25,0.0, 2.0,.5,0.0, 2.0,-.25,0.0 };
  4058.     static float box[4][3]  = { -2.0,-1.25,0.0, -2.0,1.25,0.0, 2.0,1.25,0.0,
  4059.                 2.0,-1.25,0.0 };
  4060.     ICOLOR(instrument_data.textbackground);
  4061.     bgnpolygon();
  4062.     v3f(box[0]);
  4063.     v3f(box[1]);
  4064.     v3f(box[2]);
  4065.     v3f(box[3]);
  4066.     endpolygon();
  4067.     ICOLOR(instrument_data.yellow);
  4068.     bgnpolygon();
  4069.     v3f(stripes[0]);
  4070.     v3f(stripes[1]);
  4071.     v3f(stripes[2]);
  4072.     endpolygon();
  4073.     bgnpolygon();
  4074.     v3f(stripes[3]);
  4075.     v3f(stripes[4]);
  4076.     v3f(stripes[5]);
  4077.     v3f(stripes[6]);
  4078.     endpolygon();
  4079.     bgnpolygon();
  4080.     v3f(stripes[7]);
  4081.     v3f(stripes[8]);
  4082.     v3f(stripes[9]);
  4083.     v3f(stripes[10]);
  4084.     endpolygon();
  4085.     bgnpolygon();
  4086.     v3f(stripes[11]);
  4087.     v3f(stripes[12]);
  4088.     v3f(stripes[13]);
  4089.     v3f(stripes[14]);
  4090.     endpolygon();
  4091. }
  4092.  
  4093.  
  4094. /*
  4095.  * Update the landing gear's instrument
  4096.  */
  4097. update_gear(gear_t *inst, int forceupdate)
  4098. {
  4099.     static float box[4][3]  = { -2.0,-1.25,0.0, -2.0,1.25,0.0, 2.0,1.25,0.0,
  4100.                 2.0,-1.25,0.0 };
  4101.     static float ubox[4][3] = { -2.0,1.25,0.0, -2.0,3.9,0.0, 2.0,3.9,0.0,
  4102.                 2.0,1.25,0.0 };
  4103.     int current;
  4104.     int gearstate;
  4105.     float uptrans;
  4106.     char buf[2];
  4107.  
  4108.     if (planes[0]->wheels == 0)
  4109.     gearstate = 0;
  4110.     else if (planes[0]->wheels == 10 && landing_gear_stuck != 0)
  4111.     gearstate = 2;
  4112.     else
  4113.     gearstate = 1;
  4114.  
  4115.     current = instrument_data.current;
  4116.     pushmatrix();
  4117.     translate(inst->px, inst->py, inst->pz);
  4118.     scale(inst->size, inst->size, inst->size);
  4119.  
  4120.     if ((gearstate != inst->last_state[current])||inst->forcenodraw||forceupdate)
  4121.     {
  4122.     if (gearstate == 0)
  4123.     {
  4124.         inst->forcedraw = inst->framec = inst->sliding = 0;
  4125.         pushmatrix();
  4126.         translate(-4.0,-3.0,0.0);
  4127.         ICOLOR(instrument_data.greenlamp);
  4128.         update_gear_drawlamp();
  4129.         translate(8.0,0.0,0.0);
  4130.         ICOLOR(instrument_data.greenlamp);
  4131.         update_gear_drawlamp();
  4132.         translate(-4.0,7.0,0.0);
  4133.         ICOLOR(instrument_data.greenlamp);
  4134.         update_gear_drawlamp();
  4135.         popmatrix();
  4136.         inst->last_state[current] = gearstate;
  4137.     }
  4138.     else if (((gearstate == 1)&&(inst->last_state[current] == 0))
  4139.                 ||inst->forcenodraw)
  4140.     {
  4141.         if (inst->forcenodraw)
  4142.         inst->forcenodraw--;
  4143.         else
  4144.         inst->last_state[current] = gearstate;
  4145.         inst->forcedraw = inst->framec = inst->sliding = 0;
  4146.         pushmatrix();
  4147.         translate(-4.0,-3.0,0.0);
  4148.         ICOLOR(instrument_data.redlamp);
  4149.         update_gear_drawlamp();
  4150.         translate(8.0,0.0,0.0);
  4151.         ICOLOR(instrument_data.redlamp);
  4152.         update_gear_drawlamp();
  4153.         translate(-4.0,7.0,0.0);
  4154.         ICOLOR(instrument_data.redlamp);
  4155.         update_gear_drawlamp();
  4156.         popmatrix();
  4157.     }
  4158.     else if ((gearstate == 1)&&(inst->last_state[current] == 2))
  4159.     {
  4160.         inst->sliding = 1;
  4161.         if (!inst->framec) inst->framec = 1;
  4162.     }
  4163.     else if (gearstate == 2)
  4164.     {
  4165.         inst->sliding = -1;
  4166.         if (!inst->framec) inst->framec = inst->numframes;
  4167.     }
  4168.     }
  4169.     if (inst->sliding)
  4170.     {
  4171.     uptrans = inst->framec * inst->transfactor;
  4172.     pushmatrix();
  4173.     translate(-4.0,-3.0,0.0);
  4174.     ICOLOR(instrument_data.redlamp);
  4175.     bgnpolygon();
  4176.     v3f(box[0]);
  4177.     v3f(box[1]);
  4178.     v3f(box[2]);
  4179.     v3f(box[3]);
  4180.     endpolygon();
  4181.     pushmatrix();
  4182.     translate(0.0,uptrans,0.0);
  4183.     update_gear_drawstripes();
  4184.     popmatrix();
  4185.     COLOR(C_BLACK);
  4186.     bgnpolygon();
  4187.     v3f(ubox[0]);
  4188.     v3f(ubox[1]);
  4189.     v3f(ubox[2]);
  4190.     v3f(ubox[3]);
  4191.     endpolygon();
  4192.     ICOLOR(instrument_data.textborder);
  4193.     bgnclosedline();
  4194.     v3f(box[0]);
  4195.     v3f(box[1]);
  4196.     v3f(box[2]);
  4197.     v3f(box[3]);
  4198.     endclosedline();
  4199.  
  4200.     translate(8.0,0.0,0.0);
  4201.     ICOLOR(instrument_data.redlamp);
  4202.     bgnpolygon();
  4203.     v3f(box[0]);
  4204.     v3f(box[1]);
  4205.     v3f(box[2]);
  4206.     v3f(box[3]);
  4207.     endpolygon();
  4208.     pushmatrix();
  4209.     translate(0.0,uptrans,0.0);
  4210.     update_gear_drawstripes();
  4211.     popmatrix();
  4212.     COLOR(C_BLACK);
  4213.     bgnpolygon();
  4214.     v3f(ubox[0]);
  4215.     v3f(ubox[1]);
  4216.     v3f(ubox[2]);
  4217.     v3f(ubox[3]);
  4218.     endpolygon();
  4219.     ICOLOR(instrument_data.textborder);
  4220.     bgnclosedline();
  4221.     v3f(box[0]);
  4222.     v3f(box[1]);
  4223.     v3f(box[2]);
  4224.     v3f(box[3]);
  4225.     endclosedline();
  4226.  
  4227.     translate(-4.0,7.0,0.0);
  4228.     ICOLOR(instrument_data.redlamp);
  4229.     bgnpolygon();
  4230.     v3f(box[0]);
  4231.     v3f(box[1]);
  4232.     v3f(box[2]);
  4233.     v3f(box[3]);
  4234.     endpolygon();
  4235.     pushmatrix();
  4236.     translate(0.0,uptrans,0.0);
  4237.     update_gear_drawstripes();
  4238.     popmatrix();
  4239.     COLOR(C_BLACK);
  4240.     bgnpolygon();
  4241.     v3f(ubox[0]);
  4242.     v3f(ubox[1]);
  4243.     v3f(ubox[2]);
  4244.     v3f(ubox[3]);
  4245.     endpolygon();
  4246.     ICOLOR(instrument_data.textborder);
  4247.     bgnclosedline();
  4248.     v3f(box[0]);
  4249.     v3f(box[1]);
  4250.     v3f(box[2]);
  4251.     v3f(box[3]);
  4252.     endclosedline();
  4253.     popmatrix();
  4254.  
  4255.     inst->framec += inst->sliding;
  4256.     if (!inst->framec)
  4257.     {
  4258.         inst->forcedraw = 2;
  4259.         inst->sliding = 0;
  4260.         inst->last_state[current] = inst->last_state[!current] = gearstate;
  4261.     }
  4262.     if (inst->framec >= inst->numframes)
  4263.     {
  4264.         inst->forcenodraw = 2;
  4265.         inst->framec = 0;
  4266.         inst->sliding = 0;
  4267.         inst->last_state[current] = inst->last_state[!current] = gearstate;
  4268.     }
  4269.     }
  4270.     else if (inst->forcedraw)
  4271.     {
  4272.     inst->forcedraw--;
  4273.     pushmatrix();
  4274.     translate(-4.0,-3.0,0.0);
  4275.     update_gear_drawstripes();
  4276.     ICOLOR(instrument_data.textborder);
  4277.     bgnclosedline();
  4278.     v3f(box[0]);
  4279.     v3f(box[1]);
  4280.     v3f(box[2]);
  4281.     v3f(box[3]);
  4282.     endclosedline();
  4283.  
  4284.     translate(8.0,0.0,0.0);
  4285.     update_gear_drawstripes();
  4286.     ICOLOR(instrument_data.textborder);
  4287.     bgnclosedline();
  4288.     v3f(box[0]);
  4289.     v3f(box[1]);
  4290.     v3f(box[2]);
  4291.     v3f(box[3]);
  4292.     endclosedline();
  4293.  
  4294.     translate(-4.0,7.0,0.0);
  4295.     update_gear_drawstripes();
  4296.     ICOLOR(instrument_data.textborder);
  4297.     bgnclosedline();
  4298.     v3f(box[0]);
  4299.     v3f(box[1]);
  4300.     v3f(box[2]);
  4301.     v3f(box[3]);
  4302.     endclosedline();
  4303.     popmatrix();
  4304.     inst->last_state[current] = gearstate;
  4305.     }
  4306.     popmatrix();
  4307. }
  4308.  
  4309.  
  4310.  
  4311. /*
  4312.  * Initialize the landing gear instrument
  4313.  */
  4314. void init_gear(float px, float py, float pz, float size)
  4315. {
  4316.     gear_t *inst;
  4317.  
  4318.     inst = (gear_t *)malloc(sizeof(*inst));
  4319.     bzero(inst, sizeof(*inst));
  4320.     inst->px = px;
  4321.     inst->py = py;
  4322.     inst->pz = pz;
  4323.     inst->size = size;
  4324.     inst->plateobject = plate1;
  4325.     inst->framec = 0;
  4326.     inst->last_state[0] = inst->last_state[1] = 1;
  4327.     inst->sliding = 0;
  4328.     inst->forcedraw = inst->forcenodraw = 0;
  4329.     inst->numframes = 4;
  4330.     inst->transfactor = 2.6 / inst->numframes;
  4331.  
  4332.     append_inst_list(draw_gear, update_gear, inst);
  4333. }
  4334.  
  4335.  
  4336.  
  4337. /************************************************************************
  4338. ***            G-meter functions                  ***
  4339. ************************************************************************/
  4340.  
  4341.  
  4342. typedef struct {
  4343.     float px, py, pz;        /* Position of instrument */
  4344.     float size;            /* Size of instrument */
  4345.     object_t *plateobject;
  4346.     float last_g[2];        /* Previous fuel of both buffers */
  4347.     float last_gheight[2];
  4348.     int numticks;
  4349. } gmeter_t;
  4350.  
  4351.  
  4352.  
  4353. /*
  4354.  * Draw the gmeter
  4355.  */
  4356. draw_gmeter(gmeter_t *inst)
  4357. {
  4358.     static float verts[4][3] = { -2.1,-15.1,0.0, 2.1,-15.1,0.0, 2.1,15.1,0.0,
  4359.             -2.1,15.1,0.0 };
  4360.     static float ticks[2][3]       = { -2.0,0.0,0.0, -1.2,0.0,0.0 };
  4361.     static float lticks[2][3]       = { 1.2,0.0,0.0, 2.0,0.0,0.0 };
  4362.     static float smallticks[2][3]  = { -2.0,0.0,0.0, -.8,0.0,0.0 };
  4363.     static float lsmallticks[2][3] = { 2.0,0.0,0.0, .8,0.0,0.0 };
  4364.     short sl, sr, sb, st;
  4365.     char buf[4];
  4366.     int x;
  4367.     float angstep, tickangstep;
  4368.  
  4369.     getviewport(&sl,&sr,&sb,&st);
  4370.     pushmatrix();
  4371.     translate(inst->px, inst->py, inst->pz);
  4372.     scale(inst->size, inst->size, inst->size);
  4373.  
  4374.     if (!in_cmode)
  4375.     {
  4376.     drawmode(UNDERDRAW);
  4377.     color(U_INST);
  4378.     clear_inst2();
  4379.     color(MARKINGS);
  4380.     }
  4381.     else
  4382.     {
  4383.     drawmode(PUPDRAW);
  4384.     color(U_BLACK);
  4385.     clear_inst2();
  4386.     color(P_MARKINGS);
  4387.     }
  4388.  
  4389.     for (x= -10; x<=10; x+=2)
  4390.     {
  4391.     pushmatrix();
  4392.     translate(0.0, 1.2*x, 0.0);
  4393.     bgnline();
  4394.     v3f(ticks[0]);
  4395.     v3f(ticks[1]);
  4396.     endline();
  4397.     bgnline();
  4398.     v3f(lticks[0]);
  4399.     v3f(lticks[1]);
  4400.     endline();
  4401.     if (x < 10)
  4402.     {
  4403.         translate(0.0, 1.2, 0.0);
  4404.         bgnline();
  4405.         v3f(smallticks[0]);
  4406.         v3f(smallticks[1]);
  4407.         endline();
  4408.         bgnline();
  4409.         v3f(lsmallticks[0]);
  4410.         v3f(lsmallticks[1]);
  4411.         endline();
  4412.     }
  4413.     popmatrix();
  4414.     }
  4415.     pushviewport();
  4416.     viewport(sl-instrument_data.twowide, sr-instrument_data.twowide,
  4417.         sb-instrument_data.chartall, st-instrument_data.chartall);
  4418.     for (x= -10; x<=10; x+=20)
  4419.     {
  4420.     cmov(0.0, 1.2*x, 0.0);
  4421.     sprintf(buf,"%d",abs(x));
  4422.     charstr(buf);
  4423.     }
  4424.     viewport(sl-instrument_data.charwide, sr-instrument_data.charwide,
  4425.         sb-instrument_data.chartall, st-instrument_data.chartall);
  4426.     for (x= -8; x<=8; x+=2)
  4427.     {
  4428.     cmov(0.0, 1.2*x, 0.0);
  4429.     sprintf(buf,"%d",abs(x));
  4430.     charstr(buf);
  4431.     }
  4432.     cmov(0.0, -14.1, 0.0);
  4433.     charstr("G");
  4434.     popviewport();
  4435.  
  4436.     drawmode(NORMALDRAW);
  4437.     frontbuffer(TRUE);
  4438.  
  4439.     COLOR(C_BLACK);
  4440.     clear_inst2();
  4441.  
  4442.     draw_plate(inst->plateobject, 0x3);
  4443.  
  4444.     frontbuffer(FALSE);
  4445.     popmatrix();
  4446. }
  4447.  
  4448.  
  4449. update_gmeter(gmeter_t *inst, int forceupdate)
  4450. {
  4451.     static float needle[4][3]    = {{-1.55, -0.2, 0.2}, { 1.55, -0.2, 0.2},
  4452.                     { 1.55,  0.2, 0.2}, {-1.55,  0.2, 0.2}};
  4453.     static float needlebox[4][3] = {{-1.75, -0.5, 0.0}, { 1.75, -0.5, 0.0},
  4454.                     { 1.75,  0.3, 0.0}, {-1.75,  0.3, 0.0}};
  4455.     int current;
  4456.     float gload;
  4457.  
  4458.     current = instrument_data.current;
  4459.     gload = lift / GRAVITY;
  4460.     pushmatrix();
  4461.     translate(inst->px, inst->py, inst->pz);
  4462.     scale(inst->size, inst->size, inst->size);
  4463.     if ((gload != inst->last_g[current]) || forceupdate)
  4464.     {
  4465.     inst->last_g[current] = gload;
  4466.     COLOR(C_BLACK);
  4467.     pushmatrix();
  4468.     translate(0.0, inst->last_gheight[current], 0.0);
  4469.     bgnpolygon();
  4470.     v3f(needlebox[0]);
  4471.     v3f(needlebox[1]);
  4472.     v3f(needlebox[2]);
  4473.     v3f(needlebox[3]);
  4474.     endpolygon();
  4475.     popmatrix();
  4476. #ifndef NO_MS
  4477.     if (ms_samples)
  4478.     {
  4479.         pushmatrix();
  4480.         translate(0.0, inst->last_gheight[!current], 0.0);
  4481.         bgnpolygon();
  4482.         v3f(needlebox[0]);
  4483.         v3f(needlebox[1]);
  4484.         v3f(needlebox[2]);
  4485.         v3f(needlebox[3]);
  4486.         endpolygon();
  4487.         popmatrix();
  4488.     }
  4489. #endif
  4490.  
  4491.     if (gload > 10.0)
  4492.         inst->last_gheight[current] = -12.0;
  4493.     else if (gload < -10.0)
  4494.         inst->last_gheight[current] = 12.0;
  4495.     else
  4496.         inst->last_gheight[current] = -1.2 * gload;
  4497.  
  4498.     translate(0.0, inst->last_gheight[current], 0.0);
  4499.     ICOLOR(instrument_data.jamblack);
  4500.     setpattern(SHADOW_PATTERN);
  4501.     pushmatrix();
  4502.     translate(0.2, -0.2, 0.0);
  4503.     bgnpolygon();
  4504.     v3f(needle[0]);
  4505.     v3f(needle[1]);
  4506.     v3f(needle[2]);
  4507.     v3f(needle[3]);
  4508.     endpolygon();
  4509.     setpattern(0);
  4510.     popmatrix();
  4511.  
  4512.     COLOR(C_ORANGE);
  4513.     bgnpolygon();
  4514.     v3f(needle[0]);
  4515.     v3f(needle[1]);
  4516.     v3f(needle[2]);
  4517.     v3f(needle[3]);
  4518.     endpolygon();
  4519.     }
  4520.     popmatrix();
  4521. }
  4522.  
  4523.  
  4524. void init_gmeter(float px, float py, float pz, float size)
  4525. {
  4526.     gmeter_t *inst;
  4527.  
  4528.     inst = (gmeter_t *)malloc(sizeof(*inst));
  4529.     bzero(inst, sizeof(*inst));
  4530.     inst->px = px;
  4531.     inst->py = py;
  4532.     inst->pz = pz;
  4533.     inst->size = size;
  4534.     inst->plateobject = plate3;
  4535.     inst->last_g[0]= inst->last_g[1]= .1;
  4536.  
  4537.     append_inst_list(draw_gmeter, update_gmeter, inst);
  4538. }
  4539.  
  4540.  
  4541. void draw_plate(object_t *obj, unsigned long mode)
  4542. {
  4543.     if (!in_cmode)
  4544.     {
  4545.     zbuffer(TRUE);
  4546.     lighting(TRUE);
  4547.     drawobj(obj, 0x3);
  4548.     lighting(FALSE);
  4549.     zbuffer(FALSE);
  4550.     }
  4551.     else
  4552.     {
  4553.     drawmode(plate_ci_mode);
  4554.     drawobj(obj, 0x3);
  4555.     drawmode(NORMALDRAW);
  4556.     }
  4557. }
  4558.